bzoj2741: 【FOTILE模拟赛】L
分块+可持久化Trie
取前缀和,然后搞出每个块之间的答案,不在一个块的就暴力在Trie找
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct Trie { int w[2],c; Trie(){w[0]=w[1]=0,c=0;} }tr[11000000];int trlen,rt[13000]; int insert(int now,int d) { if(now==0)now=++trlen; int ret=now; for(int i=30;i>=0;i--) { int x=(((1<<i)&d)>0); if(tr[now].w[x]==0) tr[now].w[x]=++trlen; now=tr[now].w[x]; tr[now].c++; } return ret; } int merge(int x,int y) { if(x==0||y==0)return x+y; tr[x].c+=tr[y].c; tr[x].w[0]=merge(tr[x].w[0],tr[y].w[0]); tr[x].w[1]=merge(tr[x].w[1],tr[y].w[1]); return x; } int getmax(int x,int y,int d) { int ret=0; for(int i=30;i>=0;i--) { int k=((((1<<i)&d)>0)^1); if(tr[tr[y].w[k]].c-tr[tr[x].w[k]].c>0) { ret+=(1<<i); x=tr[x].w[k],y=tr[y].w[k]; } else x=tr[x].w[k^1],y=tr[y].w[k^1]; } return ret; } int s[13000]; int block,st[13000]; int f[150][150]; int main() { freopen("L.in","r",stdin); freopen("L.out","w",stdout); int n,Q,x; scanf("%d%d",&n,&Q); s[1]=0; for(int i=1;i<=n;i++) scanf("%d",&x), s[i+1]=s[i]^x; trlen=0;memset(rt,0,sizeof(rt)); for(int i=1;i<=n+1;i++) { rt[i]=insert(rt[i],s[i]); rt[i]=merge(rt[i],rt[i-1]); } block=(int(sqrt(double(n+1))))+1; for(int i=1;i<=n+1;i++)st[i]=(i-1)/block+1; for(int i=1;i<=block;i++) { int mx=0,j=i,be=(i-1)*block+1; for(int k=be;k<=n+1;k++) { if(st[k-1]!=st[k]&&k!=be) { f[i][j]=mx; j++; } mx=max(mx,getmax(rt[be-1],rt[k],s[k])); } f[i][j]=mx; } int l,r,ans=0; while(Q--) { scanf("%d%d",&l,&r); l=( (LL(l))+(LL(ans)) )%n+1; r=( (LL(r))+(LL(ans)) )%n+1; if(l>r)swap(l,r); r++; ans=0; if(st[l]==st[r]) { for(int i=l;i<=r;i++) ans=max(ans,getmax(rt[l-1],rt[r],s[i])); } else { if(st[l]+1<=st[r]-1)ans=f[st[l]+1][st[r]-1]; for(int i=l;i<=st[l]*block;i++) ans=max(ans,getmax(rt[l-1],rt[r],s[i])); for(int i=(st[r]-1)*block+1;i<=r;i++) ans=max(ans,getmax(rt[l-1],rt[r],s[i])); } printf("%d\n",ans); } return 0; }
pain and happy in the cruel world.