类似p3261,只是我们需要分块预处理anss[i][j]第i块到第j块的答案,然后整块的部分直接获得,零散的部分暴力。
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 12001 #define MAXBIT 31 #define BN 115 int root[N],ch[N*(MAXBIT+1)][2],sz[N*(MAXBIT+1)],tot; int query(int L,int R,int W)//询问a[L...R]中W与其的最大异或值 { int ans=0; L=root[L-1];R=root[R]; for(int i=MAXBIT-1;i>=0;--i) { int Bit=(W>>i&1^1); if(sz[ch[R][Bit]]-sz[ch[L][Bit]]==0) Bit^=1; else ans+=1<<i; R=ch[R][Bit]; L=ch[L][Bit]; } return ans; } void add(int now,int W)//先add(1,0),再add(2...n+1,a[1...n]) { int old=root[now-1]; root[now]=++tot; now=root[now]; for(int i=MAXBIT-1;i>=0;--i) { int Bit=(W>>i&1); sz[now]=sz[old]+1; ch[now][Bit^1]=ch[old][Bit^1]; ch[now][Bit]=++tot; now=ch[now][Bit]; old=ch[old][Bit]; } sz[now]=sz[old]+1; } int n,m,a[N],l[BN],r[BN],anss[BN][BN],num[N],sum=1; void init() { for(int i=1;i<=sum;++i) { int res=0; for(int j=i;j<=sum;++j) { for(int k=l[j];k<=r[j];++k) res=max(res,query(l[i]-1,k-1,a[k])); anss[i][j]=res; } } } void makeblock() { int sz=sqrt(n); if(!sz) sz=1; for(;sum*sz<n;++sum) { l[sum]=r[sum-1]+1; r[sum]=sum*sz; for(int i=l[sum];i<=r[sum];++i) num[i]=sum; } l[sum]=r[sum-1]+1; r[sum]=n; for(int i=l[sum];i<=r[sum];++i) num[i]=sum; } int x,y,ans; typedef long long ll; ll L,R; int main() { scanf("%d%d",&n,&m); add(0,0); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); a[i]^=a[i-1]; add(i,a[i]); } makeblock(); init(); for(;m;--m) { scanf("%I64d%I64d",&L,&R); x=(int)min((L+(ll)ans)%(ll)n+1,(R+(ll)ans)%(ll)n+1); y=(int)max((L+(ll)ans)%(ll)n+1,(R+(ll)ans)%(ll)n+1); ans=0; if(num[x]+1>=num[y]) for(int i=x;i<=y;++i) ans=max(ans,query(x-1,i-1,a[i])); else { ans=anss[num[x]+1][num[y]-1]; for(int i=x-1;i<r[num[x]];++i) ans=max(ans,query(i+1,y,a[i])); for(int i=l[num[y]];i<=y;++i) ans=max(ans,query(x-1,i-1,a[i])); } printf("%d\n",ans); } return 0; }
时间: 2024-10-12 03:01:23