题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2741
分块+可持久化trie
f[i][j]表示第i块到第j个数的最大答案。可以通过n^1.5时间内维护出来。
然后对于询问就前面那一段暴力找和块的答案相比较就好了。
然后似乎一定要插一个0 。。。
#include<cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<set> #include<cmath> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 20050 #define inf int(1e9) #define maxd 30 #define mm 1000000007 #define ll long long using namespace std; int a[maxn]; int f[130][maxn],s[maxn*301][2],sum[maxn*301],root[maxn],pos[maxn]; int n,l,r,m,cnt,ans,len,num; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void add(int d,int x,int &y,int val){ y=++cnt; sum[y]=sum[x]+1; if (d<0) return; s[y][0]=s[x][0]; s[y][1]=s[x][1]; int p=(val>>d)&1; add(d-1,s[x][p],s[y][p],val); } int ask(int d,int x,int y,int val){ if (d<0) return 0; int p=(val>>d)&1; if (sum[s[y][p^1]]-sum[s[x][p^1]]>0) return (1<<d)+ask(d-1,s[x][p^1],s[y][p^1],val); else return ask(d-1,s[x][p],s[y][p],val); } void getans(int l,int r){ ans=0; int lx=pos[l],rx=pos[r]; if (lx<rx) ans=f[lx+1][r]; rep(i,l,min(lx*len,r)) ans=max(ans,ask(maxd,root[l],root[r+1],a[i])); printf("%d ",ans); } int main(){ n=read(); m=read(); len=sqrt(n); rep(i,1,n) a[i]=read(),a[i]=a[i]^a[i-1],pos[i]=i/len+1; rep(i,0,n) add(maxd,root[i],root[i+1],a[i]); num=n/len+1; rep(i,1,num) { int now=(i-1)*len; rep(j,now,n) f[i][j]=max(f[i][j-1],ask(maxd,root[now],root[j+1],a[j])); } ans=0; rep(i,1,m){ int x=read(),y=read(); x=((ll)x+ans)%n+1; y=((ll)y+ans)%n+1; l=min(x,y); r=max(x,y); getans(l-1,r); } return 0; }