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 }
View Code

 

 

posted @ 2017-05-05 10:24  CHADLZX  阅读(153)  评论(0编辑  收藏  举报