题目
正解
卡空间毒瘤题。
如果不卡空间,随便想想就知道怎么做(可持久化数据结构真香)……
题目相当于是选一个线段树上的长度为形式的区间,首先前提是(否则没有足够多比它小的数换进来)
无论这个区间是否包含,都要满足。并且如果区间不包含,还需要满足。
首先将的情况处理出来,用个答案数组特意去存它。
于是问题的本质就是是否
假如是离线,那么可以从小到大把数加进去,在线段树的每一层维护节点包含的最多的数字。
第层节点包含的最多的数字的个数是级别的,于是考虑反过来存:当节点包含的最多的数字是多少时,此时加入的数最大是多少。
,可以存得下。
代码
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N (1<<19)
int n,K,typ,m;
int h[N],re[N];
int ansy0[N];
int seg[N];
int ls[N*2],cnt[20],beg[20];
int main(){
freopen("arcahv.in","r",stdin);
freopen("arcahv.out","w",stdout);
scanf("%d%d%d",&n,&K,&typ);
for (int i=0;i<n;++i){
scanf("%d",&h[i]),--h[i];
re[h[i]]=i;
}
for (int i=n>>1;i<n;++i)
seg[i]=max(h[(i<<1)-n],h[(i<<1|1)-n]);
for (int l=1;l<K;++l)
for (int i=(n>>l)-1;i>=(n>>l+1);--i)
if (seg[i<<1]<seg[i<<1|1]){
ansy0[seg[i<<1]]=l;
seg[i]=seg[i<<1|1];
}
else{
ansy0[seg[i<<1|1]]=l;
seg[i]=seg[i<<1];
}
ansy0[seg[1]]=K;
for (int l=K,p=0;l>=0;--l){
beg[l]=p;
p+=1<<l;
}
memset(seg,0,sizeof seg);
for (int i=0;i<n;++i)
for (int t=re[i]+n>>1,k=1;t;t>>=1,++k){
seg[t]++;
if (seg[t]>cnt[k]){
ls[beg[k]+cnt[k]]=i;
cnt[k]++;
}
}
int ans=0;
scanf("%d",&m);
while (m--){
int x,y;
scanf("%d%d",&x,&y);
x^=typ*ans,y^=typ*ans;
--x;
if (y==0){
printf("%d\n",ans=ansy0[x]);
continue;
}
ans=0;
for (int k=K;k;--k){
if (x<(1<<k)-1)
continue;
if (ls[beg[k]+max((1<<k)-1-y,0)]<=x){
ans=k;
break;
}
}
printf("%d\n",ans);
}
return 0;
}