1. 程式人生 > >BZOJ 3166 [Heoi2013]Alo (可持久化01Trie+連結串列)

BZOJ 3166 [Heoi2013]Alo (可持久化01Trie+連結串列)

題目大意:給你一個長度為$n$的序列,讓你找出一段子序列,求其中的 次大值 異或 序列裡一個數 能得到的最大值

先對序列建出可持久化$Trie$

按元素的值從小到大遍歷,設當前元素的位置是i,找出它左右離它最近第一個比$a_{i}$的位置$l1,r1$,再找出第二個比$a_{i}$大的位置$l2,r2$,這個可以用雙向連結串列維護,保證$l1$和$r1$是$i$在連結串列裡的$L_{i},R_{i}$

那麼$a_{i}$能作為次大值出現的區間為$[l2+1,r1-1]$和$[l1+1,r2-1]$

把$a_{i}$放到可持久化$Trie$裡,找出和上述區間內的數異或能得到的最大值

然後把$a_{i}$從連結串列內刪除,因為$a_{i}$不會作為最大值影響後面的元素

 1 #include <cmath>
 2 #include <queue>
 3 #include <vector>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #define N1 50100
 8 #define N2 1600000
 9 #define MM 100
10 #define ll long long
11 #define dd double  
12 #define uint unsigned int
13
#define mod 1000000007 14 #define idx(X) (X-'a') 15 using namespace std; 16 17 int gint() 18 { 19 int ret=0,fh=1;char c=getchar(); 20 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 21 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 22 return ret*fh; 23 } 24
int bin[25]; 25 struct Trie{ 26 int ch[N2][2],num[N2],root[N1],tot; 27 void init() 28 { 29 tot=1;int x=1; 30 for(int i=29;i>=0;i--){ 31 ch[x][0]=++tot; 32 x=ch[x][0]; 33 num[x]=1; 34 } 35 } 36 void insert(int s,int rt1,int rt2,int w) 37 { 38 int x,y,p; 39 y=root[rt1]; 40 root[rt2]=++tot,x=root[rt2]; 41 for(int i=29;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(int l,int r,uint s) 50 { 51 int x,y,p;uint ans=0; 52 x=root[r],y=l<0?0:root[l]; 53 for(int i=29;i>=0;i--){ 54 p=(s&bin[i])?1:0; 55 if(num[ch[x][p^1]]-num[ch[y][p^1]]>0){ 56 x=ch[x][p^1],y=ch[y][p^1]; 57 ans|=bin[i]; 58 }else if(num[ch[x][p]]-num[ch[y][p]]>0){ 59 x=ch[x][p],y=ch[y][p]; 60 }else break; 61 }return ans; 62 } 63 }T; 64 65 int n,m; 66 uint a[N1]; 67 int L[N1],R[N1]; 68 struct node{uint w;int id;}b[N1]; 69 int cmp(node s1,node s2){return s1.w<s2.w;} 70 71 int main() 72 { 73 //freopen("1.in","r",stdin); 74 scanf("%d",&n); 75 for(int i=0;i<=29;i++) 76 bin[i]=(1<<i); 77 T.init(); 78 for(int i=1;i<=n;i++){ 79 a[i]=gint(); 80 b[i].w=a[i],b[i].id=i; 81 T.insert(a[i],i-1,i,1); 82 L[i]=i-1,R[i]=i+1; 83 } 84 sort(b+1,b+n+1,cmp); 85 int l1,r1,l2,r2; 86 uint s1,s2,ans=0; 87 for(int j=1;j<=n;j++){ 88 int i=b[j].id; 89 l1=L[i],r1=R[i]; 90 l2=L[l1],r2=R[r1]; 91 s1=0,s2=0; 92 if(l1!=0) s1=T.query(l2,r1-1,a[i]); 93 if(r1!=n+1) s2=T.query(l1,r2-1,a[i]); 94 ans=max(ans,max(s1,s2)); 95 L[R[i]]=L[i],R[L[i]]=R[i]; 96 } 97 printf("%u\n",ans); 98 return 0; 99 }