题意:
求区间的最大子区间异或和。
(n≤12000)
题解:
首先计算前缀和转化为子区间求两两异或最大值。
看到
n
<script type="math/tex" id="MathJax-Element-83">n</script>范围这么小,自然想到先分块搞搞了。。。
再套一颗可持续化Trie。。
#include<bits/stdc++.h>
using namespace std;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
inline int read(){
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i+(i<<2)<<1)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(long long x){
static int buf[50];
if(!x){ob->sputc('0');ob->sputc('\n');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])ob->sputc(buf[buf[0]--]+'0');
ob->sputc('\n');
}
}io;
const int Maxn=2e4+50;
int n,m,S,lastans,nowval,a[Maxn],sumval[Maxn],bg[Maxn],ed[Maxn],tot,pos[Maxn],ans[400][Maxn];
const int Maxdep=31;
struct node{
node *lc,*rc;
int sze;
inline void upt(){
sze=lc->sze+rc->sze;
}
}Pool[Maxn<<6],*pool=Pool,*null=Pool,*rt[Maxn];
inline node* newnode(){
++pool;
pool->lc=pool->rc=null;
return pool;
}
inline void insert(node *x,node *&y,int dep,int val){
y=newnode();y->lc=x->lc;y->rc=x->rc;y->sze=x->sze+1;
if(!dep)return;
if(val&(1<<(dep-1)))insert(x->rc,y->rc,dep-1,val);
else insert(x->lc,y->lc,dep-1,val);
}
inline int query(node *x,node *y,int dep,int val,int &t){
if(!dep)return t;
if(val&(1<<(dep-1))){
if(y->lc->sze-x->lc->sze)return query(x->lc,y->lc,dep-1,val,t);
else {t|=(1<<(dep-1));return query(x->rc,y->rc,dep-1,val,t);}
}
else{
if(y->rc->sze-x->rc->sze){t|=(1<<(dep-1));return query(x->rc,y->rc,dep-1,val,t);}
else return query(x->lc,y->lc,dep-1,val,t);
}
}
int main(){
io.init();n=io.read(),m=io.read();S=sqrt((double)n)+1;null->lc=null->rc=null;
for(int i=0;i<=n+1;i++)rt[i]=null;
insert(rt[0],rt[1],Maxdep,0);
for(int i=1;i<=n;i++){
a[i]=io.read();sumval[i]=sumval[i-1]^a[i];
insert(rt[i],rt[i+1],Maxdep,sumval[i]);
}
for(int i=1;i<=n;i+=S){
++tot;bg[tot]=i;ed[tot]=min(i+S-1,n);
for(int j=bg[tot];j<=ed[tot];j++){
pos[j]=tot;
}
}
for(int i=1;i<=tot;i++){
if(bg[i]==n)break;
ans[i][bg[i]+1]=sumval[bg[i]]^sumval[bg[i]+1];
for(int j=bg[i]+2;j<=n;j++){
int t=0;
ans[i][j]=max(ans[i][j-1],sumval[j]^query(rt[bg[i]],rt[j],Maxdep,sumval[j],t));
}
}
for(int i=1;i<=m;i++){
int l=(1ll*io.read()+lastans)%n+1,r=(1ll*io.read()+lastans)%n+1;
if(l>r)swap(l,r);l--;
if(r-l+1<2*S){
lastans=sumval[l]^sumval[l+1];
for(int j=l+2;j<=r;j++){
int t=0;
lastans=max(lastans,sumval[j]^query(rt[l],rt[j],Maxdep,sumval[j],t));
}
}
else{
int L=((l&&l==bg[pos[l]])?(pos[l]):(pos[l]+1));
lastans=ans[L][r];
for(int j=l;j<bg[L];j++){
int t=0;
lastans=max(lastans,sumval[j]^query(rt[j+1],rt[r+1],Maxdep,sumval[j],t));
}
}
io.W(lastans);
}
}