BZOJ - 4260 01字典树+前后缀

题意:给定\(a[1...n]\),求\((a_i⊕a_i+1⊕...⊕a_j)+(a_p⊕a_{p+1}⊕...⊕a_{q})\)的最大值,其中\(1≤i≤j<p≤q≤n\)

前后缀最优解预处理后然后枚举断点即可

/*H E A D*/
struct trie{
	int ch[maxn<<5][2],sz[maxn<<5],val[maxn<<5],tot,root;
	void init(){
		ch[0][0]=ch[0][1]=0;
		sz[0]=0;val[0]=0;
		tot=1;root=0;
	}
	void insert(int x){
		int c,now=root;
		for(int k = 30; k >= 0; k--){
			c=((x>>k)&1);
			if(!ch[now][c]){
				ch[tot][0]=ch[tot][1]=0;
				sz[tot]=0;val[tot]=0;
				ch[now][c]=tot++;
			}
			now=ch[now][c];
			sz[now]++;
		}
		val[now]=x;
	}
	void update(int x,int d){
		int c,now=root;
		for(int k = 30; k >= 0; k--){
			c=((x>>k)&1);
			now=ch[now][c];
			sz[now]+=d;
		}
	}
	int query(int x){
		int c,now=root;
		for(int k = 30; k >= 0; k--){
			c=((x>>k)&1);
			if(ch[now][c^1]&&sz[ch[now][c^1]]) now=ch[now][c^1];
			else now=ch[now][c];
		}
		return x^val[now];
	}
}trie;
int n,ans,a[maxn],pre[maxn],suf[maxn],mpre[maxn],msuf[maxn];
int main(){
	while(scanf("%d",&n)!=EOF){
		for(int i = 1; i <= n; i++){
			scanf("%d",&a[i]);
		}
		pre[0]=suf[n+1]=0;
		for(int i = 1; i <= n; i++){
			pre[i]=pre[i-1]^a[i];
		}
		for(int i = n; i > 0; i--){
			suf[i]=suf[i+1]^a[i];
		}
		memset(mpre,0,sizeof mpre);trie.init();trie.insert(0);
		for(int i = 1; i <= n; i++){
			mpre[i]=max(mpre[i-1],trie.query(pre[i-1]));
			trie.insert(pre[i]);
		}
		memset(msuf,0,sizeof msuf);trie.init();trie.insert(0);
//		for(int i = n; i > 0; i--){
//			msuf[i]=max(msuf[i+1],trie.query(suf[i+1]));
//			trie.insert(suf[i]);
//		}
//		ans=0;
//		for(int i = n; i > 0; i--){
//			ans=max(ans,msuf[i]+mpre[i-1]);
//		}
		for(int i = n ; i > 0; i--){
			ans=max(ans,trie.query(suf[i])+mpre[i-1]);
			trie.insert(suf[i]);
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2018-02-08 01:24  Caturra  阅读(163)  评论(0编辑  收藏  举报