bzoj 3166 [Heoi2013]Alo 可持久化Trie

筅森魡賤 提交于 2019-11-28 07:07:16

3166: [Heoi2013]Alo

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 1227  Solved: 569
[Submit][Status][Discuss]

Description

Welcome to ALO ( Arithmetic and Logistic Online)。这是一个VR MMORPG ,
如名字所见,到处充满了数学的谜题。
现在你拥有n颗宝石,每颗宝石有一个能量密度,记为ai,这些宝石的能量
密度两两不同。现在你可以选取连续的一些宝石(必须多于一个)进行融合,设为  ai, ai+1, …, a j,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值
与其他任意一颗宝石的能量密度按位异或的值,即,设该段宝石能量密度次大值
为k,则生成的宝石的能量密度为max{k xor ap | ap ≠ k , i ≤ p ≤ j}。
现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

Input

第一行,一个整数 n,表示宝石个数。 
第二行, n个整数,分别表示a1至an,表示每颗宝石的能量密度,保证对于i ≠ j有 ai ≠ aj。 
 

Output

输出一行一个整数,表示最大能生成的宝石能量密度。

Sample Input

5
9 2 1 4 7


Sample Output

14

HINT



【样例解释】

选择区间[1,5],最大值为 7 xor 9。

 

 

对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

Source

加强型数据By Hta

 

题解:这里看到了xor那么就要去想按位,因为xor与各个位之间是没有关联的。

就是每个宝石,可以操作的区间是知道的,除非它就是最大,否则找到左,右比它大的,然后

比如l和r,在l-r的可持久化字典树中去找即可。

好像有点麻烦,找区间的时候,是需要从大到小加入值,这样的话是可以找的。

 1 #pragma GCC optimize(2)
 2 #pragma G++ optimize(2)
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<set>
 9 #include<cstdlib>
10 
11 #define guide set<int>::iterator
12 #define N 50007
13 #define inf 1000000007
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
19     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 
23 int n;
24 int bin[37];
25 int ans,rt[N];
26 struct Node
27 {
28     int val,pos;
29 }a[N];
30 set<int>q;
31 
32 
33 struct trie
34 {
35     int cnt;
36     int ch[37*N][2],sum[37*N];
37     trie(){cnt=0;}
38     int insert(int x,int val)
39     {
40         int root,y;root=y=++cnt;
41         for (int i=30;i>=0;i--)
42         {
43             int t=val&bin[i];t>>=i;
44             ch[y][0]=ch[x][0],ch[y][1]=ch[x][1];
45             x=ch[x][t],y=ch[y][t]=++cnt;
46             sum[y]=sum[x]+1;
47         }
48         return root;
49     }
50     int query(int val,int yl,int xz)
51     {
52         int res=0;
53         for (int i=30;i>=0;i--)
54         {
55             int t=val&bin[i];t>>=i;
56             if(sum[ch[xz][t^1]]-sum[ch[yl][t^1]])res+=bin[i],xz=ch[xz][t^1],yl=ch[yl][t^1];
57             else xz=ch[xz][t],yl=ch[yl][t];
58         }
59         return res;
60     }
61 }trie;
62 bool operator<(Node x,Node y){return x.val>y.val;}
63 int main()
64 {
65     bin[0]=1;for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;
66     n=read();
67     for (int i=1;i<=n;i++)
68         a[i].val=read(),a[i].pos=i;
69     for (int i=1;i<=n;i++)
70         rt[i]=trie.insert(rt[i-1],a[i].val);
71     q.insert(-1),q.insert(inf),q.insert(-2),q.insert(inf+1);//因为是次小
72     sort(a+1,a+n+1),q.insert(a[1].pos);
73     for (int i=2;i<=n;i++)
74     {
75         int l=a[i].pos,r=a[i].pos,x=a[i].pos;
76         guide p,t;
77         p=t=q.upper_bound(x);
78         r=*t;t++;r=*t-1;
79         l=*--p;p--;l=*p+1;
80         l=max(1,l),r=min(n,r);
81         if(l!=r)ans=max(ans,trie.query(a[i].val,rt[l-1],rt[r]));
82         q.insert(x);
83     }
84     printf("%d",ans);
85 }

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!