BZOJ3166: [Heoi2013]Alo

时间:2023-03-09 07:43:43
BZOJ3166: [Heoi2013]Alo

3166: [Heoi2013]Alo

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 394  Solved: 204
[Submit][Status]

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

题解:
枚举这个次小值,那么它作为最小值的区间就是左边第二个比它大的数的位置+1到右边第二个比它大的数的位置-1,这一步可以用set(我刚开始居然用的单调队列。。。)
然后可持久化trie搞就行了
代码:
 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 100000+5

 #define maxm 2000000+5

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int x=,f=;char ch=getchar();

     while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}

     while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}

     return x*f;

 }
int n,mx,l[maxn],r[maxn],a[maxn],tot,sta[maxn],rt[maxn],t[maxm][],id[maxm];
pair<int,int>b[maxn];
set<int>s;
set<int>::iterator it;
inline void insert(int pre,int x,int k)
{
int now=rt[k]=++tot;id[tot]=k;
for3(i,,)
{
int j=(x>>i)&;
t[now][j^]=t[pre][j^];
t[now][j]=++tot;id[tot]=k;
now=tot;
pre=t[pre][j];
}
}
inline int query(int l,int r,int x)
{
int now=rt[r],ret=;
for3(i,,)
{
int j=((x>>i)&)^;
if(id[t[now][j]]>=l)ret|=<<i;else j^=;
now=t[now][j];
}
return ret;
}
inline int getl(int x)
{
it=s.find(x);
if(it--==s.begin())return ;
if(it--==s.begin())return ;
return *it;
}
inline int getr(int x)
{
it=s.find(x);
if(++it==s.end())return n+;
if(++it==s.end())return n+;
return *it;
} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
n=read();id[]=-;
insert(rt[],,);
for1(i,n)
{
a[i]=read();insert(rt[i-],a[i],i);mx=max(mx,a[i]);
b[i].first=a[i];b[i].second=i;
}
sort(b+,b+n+);
for3(i,n,)
{
s.insert(b[i].second);
l[b[i].second]=getl(b[i].second);
r[b[i].second]=getr(b[i].second);
}
int ans=;
for1(i,n)if(a[i]!=mx)ans=max(ans,query(l[i]+,r[i]-,a[i]));
printf("%d\n",ans); return ; }