HDU - 6621 K-th Closest Distance 主席树+二分答案

K-th Closest Distance

主席树第二波~

题意

给你\(n\)个数\(m\)个询问,问\(i\in [l,r]\)计算每一个\(|a_{i}-p|\)求出第\(k\)小
题目要求强制在线\(l = l \oplus ans、r = r \oplus ans、p = p \oplus ans、k = k \oplus ans\)(ans为上次询问的答案)

思路

  • 二分答案\(ans\),找区间\(i\in[l,r], a_{i} \in [p-ans, p+ans]\)里的数量\(>= k\)
    \(|a_{i} - p | = ans\)
    \(a_{i} - p = ans、p - a_{i} = ans\)
    \(a_{i} = ans + p、a_{i} = p - ans\)
  • 用主席树维护一下就\(ok\)了

    AC代码


#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;
struct Node{
    int l, r, cnt;
}node[maxn*40];
int w[maxn], a[maxn];
vector<int> v;

void init(){
    v.clear();
    tol = 0;
    mes(w, 0);
}

void build(int l, int r, int rt){
    rt = ++tol;
    node[rt].cnt = 0;
    if(l == r)
        return;
    int mid = l+r>>1;
    build(l, mid, node[rt].l);
    build(mid+1, r, node[rt].r);
}

void update(int l, int r, int &x, int y, int pos){
    x = ++tol;
    node[x] = node[y];
    node[x].cnt++;
    if(l == r)
        return;
    int mid = l+r>>1;
    if(pos <= mid)
        update(l, mid, node[x].l, node[y].l, pos);
    else
        update(mid+1, r, node[x].r, node[y].r, pos);
}

int query(int L, int R, int l, int r, int x, int y){
    if(L <= l && r <= R)
        return node[y].cnt - node[x].cnt;
    int mid = l+r>>1, ans = 0;
    if(L <= mid)
        ans += query(L, R, l, mid, node[x].l, node[y].l);
    if(R > mid)
        ans += query(L, R, mid+1, r, node[x].r, node[y].r);
    return ans;
}

int getid(int x){
    return lower_bound(v.begin(), v.end(), x) - v.begin()+1;
}
int getid_(int x){
    return upper_bound(v.begin(), v.end(), x) - v.begin()+1;
}

int main() {
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        init();
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        int len = v.size()+1;
        build(1, len, 1);
        for(int i = 1; i <= n; i++)
            update(1, n, w[i], w[i-1], getid(a[i]));
        int ans = 0;
        while(m--){
            int L, R, p, k;
            scanf("%d%d%d%d", &L, &R, &p, &k);
            L ^= ans; R ^= ans; p^= ans;k ^= ans;   //要记得^
            int l = 0, r = 1e6;
            while(l <= r){
                int mid = (l+r)>>1;
                int sum = query(getid(p-mid), getid_(p+mid)-1, 1, n, w[L-1], w[R]);     //第一个getid和第二个不一样
                if(sum >= k){
                    ans = mid;
                    r = mid-1;
                }
                else
                    l = mid+1;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhuyou/p/11291729.html

时间: 2024-10-11 00:31:17

HDU - 6621 K-th Closest Distance 主席树+二分答案的相关文章

[hdu-6621]K-th Closest Distance 主席树 线段树 2019 多校4

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意:给一个数组,多次询问 l,r,k,p,问 l~r区间 第k小的|p-ai|是多少1<=p.ai<1e6 .1 <= K <= 169, R - L + 1 >= K,1 <= n, m <= 10^5 题解:二分答案+主席树二分绝对值答案r,然后用主席树查[p-r , p+r]区间有多少个数,如果大于等于k个减小r并记录答案,小于k个增大r有一种情况是r满

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意: 给你n个数,有m次询问 每次问你在区间[l,r]内 第k小的|\(a_i-p\)|是多少 题解: 主席树+二分 每次二分答案 如果p+mid到p-mid的值的个数大于k个的话,mid值就是可行了,然后缩小区间往左找即可 因为保证有解,所以二分出来的mid值就是答案了 que

hdu 5592 ZYB&#39;s Premutation (线段树+二分查找)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5592 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to  restore the premutation.Pair (i,j)(i<j) is considered as a reverse

HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)

题意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 作差的绝对值的第 k 小,这个绝对值是多少 分析:首先我们先分析单次查询怎么做: 题目给出的数据与多次查询已经在提示着我们在用数据结构去解决这个问题,对于常见的处理区间的数据结构首选线段树啦: 我觉得这道题的关键在于此:我们需要去二分答案ans,  为什么呢? 我们这样观察 ,对于 | p-a[i] | <= ans  等于 p-ans<=a[i] <=p+ans   那问题就转化为查询[L,R] 区间里面

HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2那个. 思路: 主席树操作,这里的思路是从n到1开始建树.其他就是主席树查询区间第K小,计算区间不同值个数. #include <algorithm> #include <iterator> #include <iostream> #include <cstring&

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球到达某个节点上,如果x==wi,那么球停在这个节点上 .当然,这个点是叶子节点也会停止 . 如果x<wi,那么有1/2的概率走向左子树,有1/2的概率走向右子树 . 如果x>wi,那么有1/8的概率走向左子树,有7/8的概率走向右子树 . 问球经过v节点的概率 .(停在v节点也算) 解法: 在线的话每一个节点建一棵根节点到该节点的线段树,离线的话就先

HDU 4417 Super Mario ( 超级马里奥 + 主席树 + 线段树/树状数组离线处理 + 划分树 )

HDU 4417 - Super Mario ( 主席树 + 线段树/树状数组离线处理 + 划分树 ) 这道题有很多种做法,我先学习的是主席树.后面陆续补上线段树离线和划分树 题目大意就是给定一个区间给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 主席树做法: 最基本的是静态第k大,这里是求静态的 <= K,差不多,在Query操作里面需要修改修改 先建立size棵主席树,然后询问的时候统计的是 第R棵主席树中[1,K]的数量 - 第L-1棵主席树中[1,K]的数量 注意这里下标

HDU 4417:Super Mario(主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意是:给出n个数和q个询问,每个询问有一个l,r,h,问在[l,r]这个区间里面有多少个数是小于等于h的. 思路:比较裸的主席树,注意题意给的区间是从[0,n-1],一开始看错导致想错了很多东西.询问的时候如果m < h,那么左子树全部都是小于 h 的,就加上左子树的 sum,继续查右子树,否则就查左子树.最后 l == r 的时候要判下 h >= l,因为这个也错了几次.从师兄那里学习到了如果找一

COGS 930. [河南省队2012] 找第k小的数 主席树

主席树裸板子 #include<cstdio> #include<iostream> #include<algorithm> #define MAXN 100005 #define MAX 2000005 using namespace std; int sum[MAX],l[MAX],mid[MAX],r[MAX],a[MAXN],b[MAXN],n,m,sz,size,root[MAXN],cnt; void build(int &x,int z,int y