题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621
题解:建主席树,直接二分答案,查询 [p - x,p + x]的数字个数 >= k。
(
k
<
=
169
k <= 169
k<=169 是个幌子)
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#include<stdio.h>
#include<algorithm>
#include<string.h>
int t,n,m,x,y,h,tot;
const int maxn = 1e5 + 10;
const int mx = 1e6;
int val[40 * maxn],ls[40 * maxn],rs[40 * maxn];
int root[maxn],cnt,a[maxn];
void init(){
cnt = 0;
ls[0] = rs[0] = root[0] = 0;
}
void upd(int &rt,int k,int l,int r){
cnt++;
val[cnt] = val[rt];
ls[cnt] = ls[rt];
rs[cnt] = rs[rt];
rt = cnt;
val[rt]++;
if(l == r) return;
int mid = l + r >> 1;
if(k > mid) upd(rs[rt],k,mid + 1,r);
else upd(ls[rt],k,l,mid);
}
int qry_num(int i,int j,int L,int R,int l,int r) {
if(L > R) return 0;
if(L <= l && r <= R) return val[j] - val[i];
int mid = l + r >> 1;
int ans = 0;
if(L <= mid) ans += qry_num(ls[i],ls[j],L,R,l,mid);
if(mid + 1 <= R) ans += qry_num(rs[i],rs[j],L,R,mid + 1,r);
return ans;
}
int find(int i,int j,int p,int k) {
i--;
int l = 0,r = mx;
while(l < r) {
int mid = l + r >> 1;
int L = max(p - mid,1),R = min(p + mid,mx);
if(qry_num(root[i],root[j],L,R,1,mx) < k) l = mid + 1;
else r = mid;
}
return l;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
root[i] = root[i - 1];
upd(root[i],a[i],1,mx);
}
int l,r,p,k;
int ans = 0;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d%d",&l,&r,&p,&k);
l ^= ans;r ^= ans;p ^= ans;k ^= ans;
ans = find(l,r,p,k);
printf("%d\n",ans);
}
}
return 0;
}