HDU6621(K-th Closest Distance 主席树+二分答案)

题目
HDU6621(K-th Closest Distance 主席树+二分答案)_第1张图片
题意:n个数,m个询问[l,r,p,k] 区间[l,r]最接近p的第k个数。强制在线。
思路:每次二分答案mid,查找区间[l,r]里面[p-mid,p+mid]的数>=k right=mid;主席树维护.

#include
#include
using namespace std;
struct tree{int l,r,sum;}t[20000000];
int root[100001],a[100001],sz;
inline void update(int l,int r,int &x,int y,int n)
{
    t[x=(++sz)]=t[y],++t[sz].sum;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(n<=mid) update(l,mid,t[x].l,t[y].l,n);
    else update(mid+1,r,t[x].r,t[y].r,n);
}
inline int query(int cl,int cr,int l,int r,int x,int y){
    if(cl<=l&&r<=cr) return t[y].sum-t[x].sum;
    int mid=(l+r)>>1,ans=0;
    if(cl<=mid) ans+=query(cl,cr,l,mid,t[x].l,t[y].l);
    if(cr>mid) ans+=query(cl,cr,mid+1,r,t[x].r,t[y].r);
    return ans;
}
int main(){
    int T,n,m,X,Max,l,r,p,k,low,high,mid;scanf("%d",&T);
    while(T--){
        sz=X=Max=0;scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&a[i]),Max=max(Max,a[i]);
        for(int i=1;i<=n;++i) update(1,Max,root[i],root[i-1],a[i]);
        while(m--){
            scanf("%d%d%d%d",&l,&r,&p,&k);l^=X,r^=X,p^=X,k^=X;
            low=0,high=max(p-1,Max-p);
            while(low<high){
                mid=(low+high)>>1;
                if(query(max(p-mid,1),min(p+mid,Max),1,Max,root[l-1],root[r])>=k) high=mid;
                else low=mid+1;
            }
            printf("%d\n",X=high);
        }
    }
}

你可能感兴趣的:(数据结构==主席树)