BZOJ2741 【FOTILE模拟赛】L
题目描述:
对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。(强制在线)
题解:
可持久化Trie+分块。
分块处理当前块上某点为起点,块后任一点为终点的最大异或和。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 12050 #define M 6050 inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,a[N],rt[N],ans=0,wt; struct Trie { int tot,siz[35*N],ch[35*N][2]; int insert(int now,int x) { int u,ret,f=rt[now-1]; u=ret=++tot; for(int i=30;i>=0;i--) { ch[u][0]=ch[f][0],ch[u][1]=ch[f][1],siz[u]=siz[f]+1; int c = (x>>i)&1; ch[u][c]=++tot; u=ch[u][c],f=ch[f][c]; } siz[u]=siz[f]+1; return ret; } int query(int l,int r,int x) { l=rt[l],r=rt[r]; int ret = 0; for(int i=30;i>=0;i--) { int c = (x>>i)&1; if(siz[ch[r][!c]]-siz[ch[l][!c]]) { ret|=(1<<i); l=ch[l][!c],r=ch[r][!c]; }else l=ch[l][c],r=ch[r][c]; } return ret; } }tr; int f[N][150],bel[N]; int main() { n=rd()+1,m=rd(); rt[1]=tr.insert(1,0); for(int i=2;i<=n;i++) { a[i]=rd()^a[i-1]; rt[i]=tr.insert(i,a[i]); } wt=(int)sqrt(n); for(int i=1;i<=n;i++) bel[i]=(i-1)/wt; for(int j=0;j<=(n-1)/wt;j++) { int l = j*wt,r = min((j+1)*wt,n); for(int i=l+1;i<=n;i++) { f[i][j]=max(f[i-1][j],tr.query(l,r,a[i])); } } while(m--) { int l=(int)((1ll*rd()+1ll*ans)%(n-1)+1); int r=(int)((1ll*rd()+1ll*ans)%(n-1)+1); if(l>r)swap(l,r); ans=0; r++; if(bel[l]==bel[r]) { for(int i=l;i<=r;i++) ans=max(ans,tr.query(l-1,r,a[i])); }else { for(int i=l;bel[i]==bel[l];i++) ans=max(ans,tr.query(l-1,r,a[i])); for(int i=r;bel[i]==bel[r];i--) ans=max(ans,tr.query(l-1,r,a[i])); for(int i=bel[l]+1;i<bel[r];i++) ans=max(ans,f[r][i]); } printf("%d\n",ans); } return 0; }