题意就不解释了。
如果按照题意乱搞个树套树好像会T的很惨。
考虑不去修改,把绝对值看成一个值域。我们可以二分数组内元素的值,假设为
m
i
d
mid
mid, 那么我们会得到一个值域
[
p
−
m
i
d
,
p
+
m
i
d
]
[p - mid, p+mid]
[p−mid,p+mid], 答案就是求给定的数组中,落在这个值域内的元素的第
k
k
k 大, 那么这就是个区间比
k
k
k小的元素个数,不就是个主席树的板子吗。
复杂度就是 O ( q l o g ( m ) l o g ( m ) O(qlog(m)log(m) O(qlog(m)log(m)
2620ms 喜提本题rank1,,,
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e5+5;
const int MAXN = 1e6;
const int mod = 1e9+7;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
vector<int>v;
struct node{
int l,r,sum;
}hjt[maxn*40];
int a[maxn],rt[maxn],cnt;
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
void insert(int l,int r,int pre,int &now,int p){
hjt[++cnt] = hjt[pre];
now = cnt;
hjt[now].sum++;
if(l == r) return;
int mid = (l+r)>>1;
if(p <= mid) insert(l,mid,hjt[pre].l,hjt[now].l,p);
else insert(mid+1,r,hjt[pre].r,hjt[now].r,p);
}
int query(int l,int r,int L,int R,int k){
if(r <= k) return hjt[R].sum - hjt[L].sum;
int mid = (l+r)>>1;
if(k <= mid) return query(l,mid,hjt[L].l,hjt[R].l,k);
else return hjt[hjt[R].l].sum - hjt[hjt[L].l].sum + query(mid+1,r,hjt[L].r,hjt[R].r,k);
}
int main() {
int t;
cin>>t;
for(int ca = 1; ca <= t; ca++){
cnt = 0;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
a[i]=read();
for(int i = 1; i <= n; i++)
insert(1,MAXN,rt[i-1],rt[i],a[i]);
int L,R,p,k;
int ans = 0;
while(m--){
scanf("%d%d%d%d",&L,&R,&p,&k);
L = L^ans;
R = R^ans;
p = p^ans;
k = k^ans;
int l = 0, r = MAXN+2;
int sum1, sum2;
while(l <= r){
int mid = (l+r)>>1;
sum1 = query(1,MAXN,rt[L-1],rt[R],max(1,p-mid-1));
sum2 = query(1,MAXN,rt[L-1],rt[R],min(MAXN,p+mid));
if(sum2 - sum1 >= k){
ans = mid;
r = mid-1;
}else{
l = mid+1;
}
}
printf("%d\n",ans);
}
}
return 0;
}
/*
5 3
1 2 3 4 5
1 5 4 1
0
*/