1. 程式人生 > >bzoj3261: 最大異或和 可持久化字典樹模板

bzoj3261: 最大異或和 可持久化字典樹模板

roo CP 前綴和 sum oot 可持久化 可持久化字典樹 == tdi

可持久化字典樹不過記得是兩次前綴和,所以記得減2,還有p=1的情況。

#include<bits/stdc++.h>
using namespace std;
int l[18000000],r[18000000],sum[18000000],ans,a[600000],root[600000],n,m,cnt=0,l2,r2,x;
char s[6];
void add(int &rt,int pre,int val,int id)
{
	if(!rt)rt=++cnt;
	sum[rt]=sum[pre]+1;
	if(id<0)return;
	l[rt]=l[pre];r[rt]=r[pre];
	if(1<<(id)&val){r[rt]=0;add(r[rt],r[pre],val,id-1);}
	else {l[rt]=0;add(l[rt],l[pre],val,id-1);}
}
void getmaxn(int L,int R,int id,int val)
{
	if(id<0)return;
	if((1<<id)&val)
	{
		if(sum[l[R]]-sum[l[L]])
		{
			getmaxn(l[L],l[R],id-1,val);
			ans|=(1<<id);
		}
		else
		{
			getmaxn(r[L],r[R],id-1,val);
		}
	}
	else
	{
		if(sum[r[R]]-sum[r[L]])
		{
			getmaxn(r[L],r[R],id-1,val);
			ans|=(1<<id);
		}
		else
		{
			getmaxn(l[L],l[R],id-1,val);
		}
	}
}
int main()
{
	//freopen("xf.in","r",stdin);
	//freopen("xf.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){scanf("%d",&a[i]);a[i]^=a[i-1];add(root[i],root[i-1],a[i],25);}
	for(int i=1;i<=m;i++)
	{
		scanf("%s",s);
		if(s[0]==‘A‘)
		{
			scanf("%d",&a[++n]);
			a[n]^=a[n-1];
			add(root[n],root[n-1],a[n],25);
		}
		else
		{
			ans=0;
			scanf("%d%d%d",&l2,&r2,&x);
			getmaxn(root[max(l2-2,0)],root[r2-1],25,x^a[n]);
			if(l2==1)ans=max(a[n]^x,ans);
			printf("%d\n",ans);
		}
	}
	return 0;
}

  

bzoj3261: 最大異或和 可持久化字典樹模板