题意:给你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;
}