題目
正解
卡空間毒瘤題。
如果不卡空間,隨便想想就知道怎麼做(可持久化數據結構真香)……
題目相當於是選一個線段樹上的長度爲形式的區間,首先前提是(否則沒有足夠多比它小的數換進來)
無論這個區間是否包含,都要滿足。並且如果區間不包含,還需要滿足。
首先將的情況處理出來,用個答案數組特意去存它。
於是問題的本質就是是否
假如是離線,那麼可以從小到大把數加進去,在線段樹的每一層維護節點包含的最多的數字。
第層節點包含的最多的數字的個數是級別的,於是考慮反過來存:當節點包含的最多的數字是多少時,此時加入的數最大是多少。
,可以存得下。
代碼
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;
}