【BZOJ】【3166】【HEOI2013】Alo

可持久化Trie+set


  Orz zyf……

  搞区间中次大值不好搞,那么我们就反过来,找一个数,然后看它在哪些区间里是次大值……

  (然而事实上我们并不用真的把这个区间具体是什么找见,只要知道它可以跟哪一段数搞Xor就可以了!

  而这个区间就是……左边第二个比他大的数的位置+1 ~ 右边第二个比它大的数的位置-1

  这中间所有数都可以跟它搞Xor= =,我们总能找到一个相应的区间……

  (我一开始理解成,这个区间就是我们要找的,a[i]为次大数的区间,然而这不是左边有一个比它大的,右边也有一个比它大的吗?但事实上我们是直接找了能跟a[i]搞Xor的区间(并)……

 1 /**************************************************************
 2     Problem: 3166
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:796 ms
 7     Memory:28112 kb
 8 ****************************************************************/
 9  
10 //BZOJ 3166
11 #include<cstdio>
12 #include<set>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 typedef long long LL;
23 inline int getint(){
24     int r=1,v=0; char ch=getchar();
25     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
26     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
27     return r*v;
28 }
29 const int N=100010,M=2000010;
30 /*******************template********************/
31  
32 int n,mx,a[N],t[M][2],rt[N],id[M],tot;
33 set<int>s;
34 set<int>::iterator it;
35 typedef pair<int,int> pii;
36 pii b[N];
37 int l[N],r[N];
38  
39 inline void Ins(int pre,int x,int k){
40     int now=rt[k]=++tot; id[tot]=k;
41     D(i,30,0){
42         int j=(x>>i)&1;
43         t[now][j^1]=t[pre][j^1];
44         t[now][j]=++tot; id[tot]=k;
45         now=tot;
46         pre=t[pre][j];
47     }
48 }
49 inline int query(int l,int r,int x){
50     int ans=0,now=rt[r];
51     D(i,30,0){
52         int j=((x>>i)&1)^1;
53         if (id[t[now][j]]>=l) ans|=1<<i; else j^=1;
54         now=t[now][j];
55     }
56     return ans;
57 }
58 inline int getl(int x){
59     it=s.find(x);
60     if (it--==s.begin()) return 0;
61     if (it--==s.begin()) return 0;
62     return *it;
63 }
64 inline int getr(int x){
65     it=s.find(x);
66     if (++it==s.end()) return n+1;
67     if (++it==s.end()) return n+1;
68     return *it;
69 }
70  
71 int main(){
72 #ifndef ONLINE_JUDGE
73     freopen("3166.in","r",stdin);
74     freopen("3166.out","w",stdout);
75 #endif
76     n=getint();
77     id[0]=-1;
78     Ins(rt[0],0,0);
79     F(i,1,n){
80         a[i]=getint(); mx=max(mx,a[i]);
81         Ins(rt[i-1],a[i],i);
82         b[i].first=a[i];
83         b[i].second=i;
84     }
85     sort(b+1,b+n+1);
86     D(i,n,1){
87         s.insert(b[i].second);
88         l[b[i].second]=getl(b[i].second);
89         r[b[i].second]=getr(b[i].second);
90     }
91     int ans=0;
92     F(i,1,n) if (a[i]!=mx)
93         ans=max(ans,query(l[i]+1,r[i]-1,a[i]));
94     printf("%d\n",ans);
95     return 0;
96 }
View Code

3166: [Heoi2013]Alo

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 524  Solved: 262
[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

[Submit][Status][Discuss]
posted @ 2015-06-05 21:05  Tunix  阅读(...)  评论(...编辑  收藏