BZOJ 2741 【FOTILE模拟赛】L
题意:强制在线多次询问区间[l,r]内的最大连续异或和.
题解:
对序列进行前缀异或和,将问题转化成求区间[l-1,r]中的最大的两数异或和.
两个数的限制十分麻烦,尝试分块.
预处理数组f[i][j]表示第i块的最左端到j的这段区间最大的两数异或和.
显然这个数组可以在O(sqrt(n)*n*32)的时间中算出来.32是因为我们需要用到可持久化Trie.
对于每个询问.
如果询问的区间中含有块的左端点,利用f数组直接递推出剩下的答案.否则暴力算即可.
时间复杂度O(sqrt(n)*n*logw+sqrt(n)*m*log);
代码复杂度低.
没有去掉打表,WA了一次,遗憾.
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define FILE "dealing" 5 #define up(i,j,n) for(int i=j;i<=n;i++) 6 #define db long double 7 #define pii pair<int,int> 8 #define pb push_back 9 #define mem(a,L) memset(a,0,sizeof(int)*(L+1)) 10 template<class T> inline bool cmin(T& a,T b){return a>b?a=b,true:false;} 11 template<class T> inline bool cmax(T& a,T b){return a<b?a=b,true:false;} 12 template<class T> inline T squ(T a){return a*a;} 13 const ll maxn=2000100+10,MAXN=20200,mod=1e9+7,limit=1e7,base=23; 14 int read(){ 15 int x=0,f=1,ch=getchar(); 16 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 17 while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 18 return x*f; 19 } 20 int n,m; 21 int a[MAXN],root[MAXN],c[maxn][2],sum[maxn],cnt,blo,f[200][12100]; 22 void updata(int o){ 23 sum[o]=sum[c[o][0]]+sum[c[o][1]]; 24 } 25 void insert(int pre,int& o,int key,int dep){ 26 o=++cnt; 27 if(dep==-1){ 28 sum[o]=sum[pre]+1; 29 return; 30 } 31 if(key&(1<<dep))c[o][0]=c[pre][0],insert(c[pre][1],c[o][1],key,dep-1); 32 else c[o][1]=c[pre][1],insert(c[pre][0],c[o][0],key,dep-1); 33 updata(o); 34 } 35 int ask(int pre,int o,int key,int k,int dep){ 36 if(dep==-1)return key; 37 int d=(k&(1<<dep))?1:0; 38 if(sum[c[o][d^1]]-sum[c[pre][d^1]])return ask(c[pre][d^1],c[o][d^1],key|(1<<dep),k,dep-1); 39 else return ask(c[pre][d],c[o][d],key,k,dep-1); 40 } 41 int main(){ 42 freopen(FILE".in","r",stdin); 43 freopen(FILE".out","w",stdout); 44 n=read(),m=read(); 45 up(i,1,n)a[i]=read()^a[i-1]; 46 up(i,0,n)insert((!i)?0:root[i-1],root[i],a[i],30); 47 blo=(int)sqrt(n+1.0)+1; 48 for(int i=0;i<=n;i+=blo) 49 for(int j=i+1;j<=n;j++) 50 f[i/blo][j]=max(f[i/blo][j-1],ask((!i)?0:root[i-1],root[j-1],0,a[j],30)); 51 ll lastans=0; 52 up(i,1,m){ 53 int x=read(),y=read(),l,r; 54 l=min(((ll)x+lastans)%n+1,((ll)y+lastans)%n+1)-1; 55 r=max(((ll)x+lastans)%n+1,((ll)y+lastans)%n+1); 56 int s=l; 57 while(s%blo&&s<n&&s<r)s++; 58 if(s==r){ 59 int ans=0; 60 for(int j=l+1;j<=r;j++) 61 cmax(ans,ask((!l)?0:root[l-1],root[j-1],0,a[j],30)); 62 printf("%lld\n",lastans=ans); 63 } 64 else { 65 int ans=f[s/blo][r]; 66 for(int j=s-1;j>=l;j--) 67 cmax(ans,ask(root[j],root[r],0,a[j],30)); 68 printf("%lld\n",lastans=ans); 69 } 70 } 71 return 0; 72 }