3166: [Heoi2013]Alo

这题大意是给你一个序列,求一个最优区间[l,r],使其中的次大值xor上区间中任意另一个数,使xor和最大(对不起,我又语死了)

这题其实暴力能a= =

但是写暴力太没节操了(- -b)

网上似乎没有除暴力以外的题解= =我来写一篇吧= =

我的大致想法就是用线段树维护i前面第二个比他大的值f[i](这里可以用权值线段树),然后用函数式trie找(f[i]+1,i)上与a[i]的最大xor。。

貌似很基础的样子= =也很暴力= =

有更优解请告诉我= =

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3000010;
struct re{
	int l,r,lc,rc,ms,mf;
} t[N];
int root[N],col[N],a[N],b[N],c[N],d[N];
int tr[N][2];
int n,sum=0,num=0,tot=0,ans=0;
inline void inse(int pp,int i,int x){
	root[i]=++sum;
	int pos=root[i];
	col[pos]=i;
	for (int j=30;j>=0;j--){
		int y=(x>>j)&1;
		tr[pos][y^1]=tr[pp][y^1];
		tr[pos][y]=++sum;
		col[sum]=i;
		pos=tr[pos][y];
		pp=tr[pp][y];
	}
}
inline int ques(int l,int r,int x){
	int pos=root[r];
	int ans=0;
	for (int j=30;j>=0;j--){
		int z=(x>>j)&1;
		if (col[tr[pos][z^1]]>=l){
			ans+=1<<j;
			pos=tr[pos][z^1];
		}else pos=tr[pos][z];
	}
	return ans;
}
inline int buildtree(int l,int r){
	int x=++num;
	t[x].l=l;
	t[x].r=r;
	t[x].mf=t[x].ms=0;
	if (l==r){
		t[x].lc=t[x].rc=0;
		return x;
	}
	int mm=(l+r)/2;
	t[x].lc=buildtree(l,mm);
	t[x].rc=buildtree(mm+1,r);
	return x;
}
inline void renew(int c,int x){
	if (t[x].mf<c){
		t[x].ms=t[x].mf;
		t[x].mf=c;
		return;
	}
	if (t[x].mf==c) return;
	if (t[x].ms<c) t[x].ms=c;
}
inline void down(int x){
	int l=t[x].lc,r=t[x].rc;
	renew(t[x].ms,l);
	renew(t[x].mf,l);
	renew(t[x].ms,r);
	renew(t[x].mf,r);
}
inline int query(int x,int pos){
	if (t[x].l==t[x].r) return t[x].ms;
	down(x);
	int mm=(t[x].l+t[x].r)/2;
	if (pos<=mm) return query(t[x].lc,pos);
	return query(t[x].rc,pos);
}
inline void add(int x,int l,int r,int c){
	if (t[x].l==0) return;
	if (l<=t[x].l&&t[x].r<=r){
		t[x].ms=t[x].mf;
		t[x].mf=c;
		return;
	}
	down(x);
	int mm=(t[x].l+t[x].r)/2;
	if (l<=mm) add(t[x].lc,l,r,c);
	if (mm<r) add(t[x].rc,l,r,c);
}
inline void calc(){
	memset(col,0,sizeof(col));
	memset(tr,0,sizeof(tr));
	sum=0; tot=0;
	inse(0,0,0);
	for (int i=1;i<=n;i++){
		b[++tot]=a[i];
		inse(root[i-1],i,a[i]);
	}
	std::sort(b+1,b+n+1);
	for (int i=1;i<=n;i++){
		c[i]=lower_bound(b+1,b+n+1,a[i])-b;
	}
	num=0;
	int ro=buildtree(1,n);
	for (int i=1;i<=n;i++){
		int x;
		x=query(ro,c[i]);
		x++;
		ans=max(ans,ques(x,i,a[i]));
		if (c[i]>1) add(ro,1,c[i]-1,i);
	}
}
inline void read(int &T){
	int ch=getchar();
	while (ch<'0'||ch>'9'){
		ch=getchar();
	}
	T=0;
	while (ch>='0'&&ch<='9'){
		T=T*10+ch-'0';
		ch=getchar();
	}
}
int main(){
	scanf("%d",&n);
	num=0;
	for (int i=1;i<=n;i++){
		scanf("%d",&d[i]);
		a[i]=d[i];
	}
	calc();
	for (int i=1;i<=n;i++) a[i]=d[n-i+1];
	calc();
	printf("%d\n",ans);
}