BZOJ 2741 L (可持久化01Trie+分块)

题目大意:给你一个序列,共有$q$个询问,每次询问区间$[L,R]$内最大连续字段异或和,强制在线,$n<=12000,m<=5000$

有个细节没处理好$WA$了好久..还有一次$ans$没清零

先对序列建出可持久化$01Trie$

分块预处理出,任意两块所覆盖区域的最大$xor$和,枚举右侧块内的每个数,然后在$01Trie$里查找即可,预处理总时间$O(n \sqrt n)$

对于每次询问,中间部分的答案可以$O(1)$得到

边界情况,左侧不完整块内的每个数都要分别作为区间左端点右端点在$01Trie$里查找最大值

右侧不完整块内的每个数作为区间右端点在01Trie里查找最大值即可,因为一旦出现它作为左端点的情况,它右面的数一定会作为右端点查询到它

时间$O(q\sqrt n+n\sqrt n)$

数据还挺强的

  1 #include <cmath>
  2 #include <queue>
  3 #include <vector>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <algorithm>
  7 #define N1 12100
  8 #define N2 420100
  9 #define M1 120
 10 #define ll long long
 11 #define dd double  
 12 #define uint unsigned int
 13 using namespace std;
 14 
 15 int gint()
 16 {
 17     int ret=0,fh=1;char c=getchar();
 18     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 19     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
 20     return ret*fh;
 21 }
 22 
 23 int n,m,sq,tq;
 24 uint bin[35];
 25 
 26 struct Trie{
 27 int ch[N2][2],num[N2],root[N1],tot;
 28 void build()
 29 {
 30     root[0]=tot=1;int x=1;
 31     for(int i=31;i>=0;i--){
 32         ch[x][0]=++tot;
 33         x=ch[x][0],num[x]=1;
 34     }
 35 }
 36 void insert(uint s,int rt1,int rt2,int w)
 37 {
 38     int x,y,p;
 39     y=root[rt1];
 40     x=root[rt2]=++tot;
 41     for(int i=31;i>=0;i--){
 42         p=(s&bin[i])?1:0;
 43         ch[x][p]=++tot;
 44         ch[x][p^1]=ch[y][p^1];
 45         num[ch[x][p]]=num[ch[y][p]]+w;
 46         x=ch[x][p],y=ch[y][p];
 47     }
 48 }
 49 uint query(uint s,int l,int r)
 50 {
 51     int x,y,p;uint ans=0;
 52     x=root[r];
 53     y=l<0?0:root[l];
 54     for(int i=31;i>=0;i--){
 55         p=(s&bin[i])?1:0;
 56         if(num[ch[x][p^1]]-num[ch[y][p^1]]>0){
 57             x=ch[x][p^1],y=ch[y][p^1];
 58             ans|=bin[i];
 59         }else if(num[ch[x][p]]-num[ch[y][p]]>0){
 60             x=ch[x][p],y=ch[y][p];
 61         }else break;
 62     }return ans;
 63 }
 64 }T;
 65 
 66 uint a[N1],pa[N1];
 67 uint s1[M1][M1];
 68 int L[M1],R[M1];
 69 
 70 int main()
 71 {
 72     scanf("%d%d",&n,&m);
 73     for(int i=0;i<=31;i++)
 74         bin[i]=(1<<i);
 75     int x,y;
 76     T.build();
 77     for(int i=1;i<=n;i++)
 78     {
 79         a[i]=gint();
 80         pa[i]=pa[i-1]^a[i];
 81         T.insert(pa[i],i-1,i,1);
 82     }
 83     sq=sqrt(n);tq=n/sq;
 84     for(int i=1;i<=tq+1;i++)
 85         L[i]=(i-1)*sq+1,R[i]=min(n,i*sq);
 86     for(int i=1;i<=tq;i++)
 87     for(int j=i;j<=tq;j++)
 88     {
 89         s1[i][j]=s1[i][j-1];
 90         for(int k=L[j];k<=R[j];k++)
 91             s1[i][j]=max(s1[i][j],T.query(pa[k],L[i]-2,k-1));
 92     }
 93     uint ans=0;int px,py;
 94     for(int j=1;j<=m;j++)
 95     {
 96         x=gint(),y=gint();
 97         x=(ans+x)%n+1,y=(ans+y)%n+1;
 98         if(x>y) swap(x,y);
 99         px=(x-1)/sq+1,py=(y-1)/sq+1;
100         if(px!=py){
101             ans=s1[px+1][py-1];
102             for(int i=x;i<=R[px];i++)
103                 ans=max(ans,T.query(pa[i],x-2,i-1));
104             for(int i=x-1;i<=R[px]-1;i++)
105                 ans=max(ans,T.query(pa[i],i,y));
106             for(int i=L[py];i<=y;i++)
107                 ans=max(ans,T.query(pa[i],x-2,i-1));
108         }else{
109             ans=0;
110             for(int i=x;i<=y;i++)
111                 ans=max(ans,T.query(pa[i],x-2,i-1));
112         }
113         printf("%u\n",ans);
114     }
115     return 0;
116 }

 

转载于:https://www.cnblogs.com/guapisolo/p/10032467.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值