zoukankan      html  css  js  c++  java
  • HDU 6521 K-th Closest Distance (主席树+二分)

    题意:

    给你一个数组,q次询问,每次问你[l,r]范围内与p距离第k大的元素的与p的距离,强制在线

    思路:

    主席树提取出[l,r]内的权值线段树,然后二分与p的距离mid

    ask该权值线段树里[p-mid,p+mid]的数的个数,使其刚好大于等于k

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e7+2e6+100;
    const int maxm = 4e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int ls[maxn],rs[maxn],dat[maxn];
    int tot;
    int n,q;
    int a[maxm];
    int root[maxm];
    int t;
    int insert(int now, int l, int r, int x, int val){
        int p = ++tot;
        ls[p]=ls[now];rs[p]=rs[now];dat[p]=dat[now];
        if(l==r){
            dat[p]+=val;
            return p;
        }
        int mid = (l+r)>>1;
        if(x<=mid)ls[p]=insert(ls[now],l,mid,x,val);
        else rs[p]=insert(rs[now],mid+1,r,x,val);
        dat[p]=dat[ls[p]]+dat[rs[p]];
        return p;
    }
    int ask(int lst, int now, int l, int r, int L, int R){
        //printf("%d %d %d %d %d %d
    ",lst,now,l,r,L,R);
        int mid = (l+r)>>1;
        int ans = 0;
        if(L<=l&&r<=R)return dat[now]-dat[lst];
        if(L<=mid)ans+=ask(ls[lst],ls[now],l,mid,L,R);
        if(mid<R)ans+=ask(rs[lst],rs[now],mid+1,r,L,R);
        return ans;
    }
    int K,p;
    bool cmp(int a, int b){
        return abs(a-p)<abs(b-p);
    }
    
    int main(){
        scanf("%d", &t);
    
        while(t--){
            int lstans = 0;
            mem(dat,0);
            tot=0;
            scanf("%d %d", &n, &q);
            for(int i = 1; i <= n; i++){
                scanf("%d", &a[i]);
                root[i]=insert(root[i-1],1,1000000,a[i],1);
            }
    
    
    
            while(q--){
                int l, r;
                scanf("%d %d %d %d", &l, &r, &p, &K);
                l^=lstans;
                r^=lstans;
                p^=lstans;
                K^=lstans;
                int ans;
                int L = 0;
                int R = 1000000;
                while(L<=R){
                    int mid = (L+R)>>1;
                    int res = ask(root[l-1],root[r],1,1000000,max(1,p-mid),min(1000000,p+mid));
                    if(res>=K){
                        ans=mid;
                        R=mid-1;
                    }
                    else L=mid+1;
                }
                lstans=ans;
                printf("%d
    ",ans);
    
            }
        }
        return 0;
    }
    /*
    1
    5 2
    31 2 5 45 4
    1 5 5 1
    2 5 3 2
    
     */
  • 相关阅读:
    数论:扩展欧几里得算法
    数论:四大定理
    数论:完全数
    数论:求解不定方程和同余方程的实验范例
    Python记:列表和元组之序列相加
    动态规划入门:热血实战!
    Python记通用列表操作之切片!
    Python记:索引操作示例:将以数指定年,月,日的日期打印出来
    计算机的性能指标
    动态规划入门(2):01背包问题实践
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11278800.html
Copyright © 2011-2022 走看看