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 }

 

posted @ 2018-11-27 18:30  guapisolo  阅读(266)  评论(0编辑  收藏  举报