线段树每个结点维护一个有序序列。。。合并两个区间用归并排序维护有序性。
查询时查询 区间L-R中值为x-y之间数的个数。8000多ms
也可以用主席树维护 3000多ms。。
然后以数值p为中点,往两边扩展d。。这个d具有单调性 可二分。
如果p-d -- p+d 区间数刚好K个 那么 d就是答案。。(第K小的 p-a[i]的距离)
复杂度nlog^2n
#include<bits/stdc++.h>
#define ls o<<1
#define rs o<<1|1
#define mm (l+r)/2
using namespace std;
const int M=100000+77;
vector<int> v[M*25];
int a[M<<2];
void build(int o,int l,int r)
{
v[o].clear();
if(l==r)
{
v[o].push_back(a[l]);
return ;
}
build(ls,l,mm);
build(rs,mm+1,r);
int i=0,j=0;
int nl=v[ls].size();
int nr=v[rs].size();
while(i<nl&&j<nr)
{
if(v[ls][i]<=v[rs][j])
{
v[o].push_back(v[ls][i]);
i++;
}
else
{
v[o].push_back(v[rs][j]);
j++;
}
}
while(i<nl)
{
v[o].push_back(v[ls][i]);
i++;
}
while(j<nr)
{
v[o].push_back(v[rs][j]);
j++;
}
}
int query(int o,int l,int r,int L,int R,int x,int y)//L-R区间 值为x-y之间的数的个数
{
if(x>y)return 0;
if(L<=l&&r<=R)
{
return upper_bound(v[o].begin(),v[o].end(),y)-lower_bound(v[o].begin(),v[o].end(),x);
}
int res=0;
if(L<=mm)res+=query(ls,l,mm,L,R,x,y);
if(R>mm)res+=query(rs,mm+1,r,L,R,x,y);
return res;
}
int main()
{
int X,N,M,T,L,R,p,K;
scanf("%d",&T);
while(T--)
{
X=0;
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
build(1,1,N);
while(M--)
{
scanf("%d%d%d%d",&L,&R,&p,&K);
L^=X,R^=X,p^=X,K^=X;
int l=0,r=1000000+7,mid,pos=r;
while(l<=r)
{
mid=(l+r)/2;
if(query(1,1,N,L,R,p-mid,p+mid)>=K)
{
r=mid-1;
pos=mid;
}
else
{
l=mid+1;
}
}
X=pos;
printf("%d\n",X);
}
}
return 0;
}
/*
1
5 1
31 2 5 45 4
1 5 5 1
*/
主席树写法
#include<bits/stdc++.h>
#define ls o<<1
#define rs o<<1|1
#define mm (l+r)/2
using namespace std;
const int M=1e6+77;
struct node
{
int sum,l,r;
}T[M*25];
int a[M],root[M];
int now;
void update(int l,int r,int &x,int y,int pos)
{
T[++now]=T[y],T[now].sum++,x=now;
if(l==r)return ;
int mid=(l+r)/2;
if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos);
else update(mid+1,r,T[x].r,T[y].r,pos);
}
int c(int l,int r,int x,int y,int L,int R){
if(l>=L&&R>=r)return T[y].sum-T[x].sum;
int mid=l+r>>1;
int ans=0;
if(L<=mid)ans+=c(l,mid,T[x].l,T[y].l,L,R);
if(R>mid)ans+=c(mid+1,r,T[x].r,T[y].r,L,R);
return ans;
}
int main()
{
int X,N,M,t,L,R,p,K;
scanf("%d",&t);
while(t--)
{
X=0,now=0;
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
for(int i=1;i<=N;i++)update(1,1000000,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;
int l=0,r=1000000+7,mid,pos=r;
while(l<=r)
{
mid=(l+r)/2;
if(c(1,1000000,root[L-1],root[R],p-mid,p+mid)>=K)
{
r=mid-1;
pos=mid;
}
else
{
l=mid+1;
}
}
X=pos;
printf("%d\n",X);
}
}
return 0;
}
/*
1
5 1
31 2 5 45 4
1 5 5 1
*/