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

题目
在这里插入图片描述
题意:n个数,m个询问[l,r,p,k] 区间[l,r]最接近p的第k个数。强制在线。
思路:每次二分答案mid,查找区间[l,r]里面[p-mid,p+mid]的数>=k right=mid;主席树维护.

#include<cstdio>
#include<algorithm>
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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值