bzoj 3166 [Heoi2013]Alo 可持久化Trie
3166: [Heoi2013]Alo
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 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
9 2 1 4 7
Sample Output
14
HINT
【样例解释】
选择区间[1,5],最大值为 7 xor 9。
对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9
Source
题解:这里看到了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 }