题意:0操作,询问[l,r]区间内选取一些数的最大区间异或和。1操作在原数组后加一个数。注意强制在线
#include<iostream>
using namespace std;
struct node{
int idd,num;
}sub[1000000+10][32];
int a[1000000+10];
int main(){
int t;
scanf("%d",&t);
for(int i=0;i<=1000000;i++)
for(int j=0;j<31;j++)sub[i][j].num=-1;
while(t--){
int n,m,preans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=0;j<31;j++)sub[i][j]=sub[i-1][j];
int tmp=a[i],id=i;
for(int j=30;j>=0;j--){
if((tmp>>j)&1==1){
if(sub[i][j].num==-1){
//printf("%d %d---\n",i,j);
sub[i][j]={id,tmp};
break;
}
else if(id>sub[i][j].idd){
node nw=sub[i][j];
sub[i][j]={id,tmp};
tmp=nw.num;
id=nw.idd;
}
tmp^=sub[i][j].num;
}
}
}
for(int i=0;i<m;i++){
int op;
scanf("%d",&op);
if(op==1){
n++;
scanf("%d",&a[n]);
a[n]^=preans;
for(int j=0;j<31;j++)sub[n][j]=sub[n-1][j];
int tmp=a[n],id=n;
for(int j=30;j>=0;j--){
if((tmp>>j)&1){
if(sub[n][j].num==-1){
sub[n][j]={id,tmp};
break;
}
else if(id>sub[n][j].idd){
node nw=sub[n][j];
sub[n][j]={id,tmp};
tmp=nw.num;
id=nw.idd;
}
tmp^=sub[n][j].num;
}
}
}
else{
int l,r,ans=0;
scanf("%d%d",&l,&r);
l=(l^preans)%n+1;
r=(r^preans)%n+1;
if(l>r)swap(l,r);
//for(int i=0;i<5;i++)printf("i=%d %d\n",i,sub[2][i].num);
for(int j=30;j>=0;j--){
if(sub[r][j].idd>=l){
ans=max(ans,sub[r][j].num^ans);
}
}
printf("%d\n",ans);
preans=ans;
}
}
}
return 0;
}