bzoj3166: [Heoi2013]Alo
3166: [Heoi2013]Alo
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 833 Solved: 398
[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
贪心求出可行的区间
按照权值的倒序,set维护位置,依次插入,则x的可行区间为[x前驱的前驱+1,x后继的后继-1]
可持久化trie维护答案
1 #include<bits/stdc++.h> 2 #define rep(i,l,r) for(int i=l;i<=r;++i) 3 using namespace std; 4 const int N=15023333,inf=2147483640; 5 set<int>q; 6 struct zs{ 7 int pos,val; 8 }a[51000]; 9 int n,m,two[31],l,r,x,rt[51000],ch[N][2],cnt,sum[N],ans; 10 int add(int x,int val){ 11 int tmp,y=tmp=++cnt,t; 12 for(int i=30;i>=0;--i){ 13 ch[y][0]=ch[x][0]; ch[y][1]=ch[x][1]; 14 sum[y]=sum[x]+1; 15 t=val&two[i]; t>>=i; 16 x=ch[x][t]; 17 y=ch[y][t]=++cnt; 18 } 19 sum[y]=sum[x]+1; 20 return tmp; 21 } 22 inline int que(int l,int r,int val){ 23 int tmp=0,t; 24 for(int i=30;i>=0;i--){ 25 t=val&two[i]; t>>=i; 26 if(sum[ch[r][t^1]]-sum[ch[l][t^1]]) tmp+=two[i],r=ch[r][t^1],l=ch[l][t^1]; 27 else r=ch[r][t],l=ch[l][t]; 28 } 29 return tmp; 30 } 31 bool cmp(zs a,zs b){ 32 return a.val>b.val; 33 } 34 int main(){ 35 two[0]=1; rep(i,1,30) two[i]=two[i-1]*2; 36 scanf("%d",&n); 37 rep(i,1,n)scanf("%d",&a[i].val),a[i].pos=i; 38 rep(i,1,n)rt[i]=add(rt[i-1],a[i].val); 39 q.insert(-1);q.insert(inf);q.insert(-2);q.insert(inf+1); 40 sort(a+1,a+n+1,cmp); 41 q.insert(a[1].pos); 42 rep(i,2,n){ 43 int l=a[i].pos,r=a[i].pos,x=a[i].pos; 44 set<int>::iterator t,p; 45 p=q.lower_bound(x); 46 t=p; 47 r=*t;t++;r=*t-1; 48 l=*--p;p--;l=*p+1; 49 l=max(1,l);r=min(r,n); 50 if(l!=r)ans=max(ans,que(rt[l-1],rt[r],a[i].val)); 51 q.insert(x); 52 } 53 printf("%d\n",ans); 54 }