不用离散化建立主席树,直接建树,二分绝对值ans,让主席树查找[p-ans,p+ans]之间的数是不是又k个,如果是,那么答案就是ans,加个build清空数组就从4秒到超时,虽然它确实没用。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<math.h>
#include<time.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+100;
int N=1e6;
int tot=0;
int a[maxn],s[maxn],L[maxn*21],R[maxn*21];
int sum[maxn*21],T[maxn];
void update(int l,int r,int &rt,int pre,int x)
{
rt=++tot;
L[rt]=L[pre];
R[rt]=R[pre];
sum[rt]=sum[pre]+1;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)update(l,mid,L[rt],L[pre],x);
else update(mid+1,r,R[rt],R[pre],x);
}
int query(int L1,int R1,int l,int r,int tl,int tr)
{
if(L1<=l && r<=R1)return sum[tr]-sum[tl];
int ANS=0,mid=(l+r)>>1;
if(L1<=mid)ANS+=query(L1,R1,l,mid,L[tl],L[tr]);
if(R1>mid)ANS+=query(L1,R1,mid+1,r,R[tl],R[tr]);
return ANS;
}
int jud(int x,int len,int l,int r)
{
int L1=max(1,x-len);
int R1=min(N,x+len);
int k=query(L1,R1,1,N,T[l-1],T[r]);
return k;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
tot=0;
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
update(1,N,T[i],T[i-1],x);
}
int ans=0;
while(q--){
int l,r,p,k;
scanf("%d%d%d%d",&l,&r,&p,&k);
l^=ans;r^=ans;p^=ans;k^=ans;
int l1=0,r1=N;
while(l1<r1){
int mid=(l1+r1)>>1;
int res=jud(p,mid,l,r);
if(res<k){
l1=mid+1;
}
else{
r1=mid;
}
}
printf("%d\n",ans=l1);
}
}
return 0;
}