2019 Multi-University Training Contest 4 K-th Closest Distance(二分+主席树)

题意:给你n个数和q次查询,查询[l , r] 内, | a[i] - p | 第k小的数

思路:二分答案,check的话就判断[l , r]区间内,[p-mid,p+mid]区间内数的个数和k的关系,若大于,则往左半边找,若小于则往右半边找

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxnn=1e6+10;
int a[maxn],T[maxn],tot,n,q;
struct node
{
    int ls,rs,sum;
}tree[maxnn*30];
int build1(int l,int r)
{
    int rt=++tot;
    tree[rt].sum=0;
    if(l!=r)
    {
        int mid=(l+r)>>1;
        tree[rt].ls=build1(l,mid);
        tree[rt].rs=build1(mid+1,r);
    }
    return rt;
}
int build2(int l,int r,int last,int val)
{
    int rt=++tot;
    tree[rt]=tree[last];
    tree[rt].sum++;
    if(l!=r)
    {
        int mid=(l+r)>>1;
        if(val<=mid)
            tree[rt].ls=build2(l,mid,tree[last].ls,val);
        else
            tree[rt].rs=build2(mid+1,r,tree[last].rs,val);
    }
    return rt;
}
int query(int l,int r,int x,int ql,int qr)
{
    if(ql<=l&&qr>=r)
        return tree[x].sum;
    int mid=(l+r)>>1;
    if(qr<=mid)
        return query(l,mid,tree[x].ls,ql,qr);
    else
        if(ql>=mid+1)
            return query(mid+1,r,tree[x].rs,ql,qr);
        else
            return query(l,mid,tree[x].ls,ql,qr)+query(mid+1,r,tree[x].rs,ql,qr);
}
int main(){
    int t,preans;
    scanf("%d",&t);
    while(t--)
    {
        tot=preans=0;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
            scanf("%d",&(a[i]));
        T[0]=build1(1,maxnn);
        for(int i=1;i<=n;i++)
            T[i]=build2(1,maxnn,T[i-1],a[i]);
        while(q--)
        {
            int l,r,p,k,low=0,high=maxnn,mid;
            scanf("%d%d%d%d",&l,&r,&p,&k);
            l^=preans,r^=preans,p^=preans,k^=preans;
            while(low<=high)
            {
                mid=(low+high)>>1;
                int tmp=query(1,maxnn,T[r],max(1,p-mid),min(p+mid,maxnn))-query(1,maxnn,T[l-1],max(1,p-mid),min(p+mid,maxnn));
                if(tmp>=k)
                    preans = mid,high=mid-1;
                else
                    low=mid+1;
            }
            printf("%d
",preans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/eason9906/p/11754728.html