1. 程式人生 > >BZOJ 2741 L (可持久化01Trie+分塊)

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 }