最大异或和

link

可持久化Trie的又一个板子。

插入很好说,直接用insert就可以了。查询其实也还好,我们知道异或有一些好用的性质,比如:

\[A\oplus A=0 \]

所以令

\[s_i=a_1\oplus a_2\oplus\cdots\oplus a_i \]

则有

\[a_l\oplus a_{l+1}\oplus\cdots\oplus a_r=s_{l-1}\oplus s_r \]

所以要求

\[a[p]\oplus a[p+1]\oplus\cdots\oplus a[N]\oplus x(p\in[l,r]) \]

的最大值,就是要求

\[s_{p-1}\oplus s_N\oplus x(p\in[l,r]) \]

的最大值。后面的部分是确定不变的,所以问题就变成了一个可持久化Trie上跑01Trie求异或和最大值的板子了。(打那么多公式只是因为新学了一个Latex很兴奋)

其它便没有什么了。要注意的就是当l为1时查询区间会覆盖到0号位置,需要特殊处理一下。代码:

#include<cstdio>
//#define zczc
const int N=600010;
const int S=32;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}
inline bool op(){
	char w=getchar();
	while(w!='A'&&w!='Q')w=getchar();
	return w=='A';
}

int m,n;

int root[N],cnt;
struct node{
	int ch[2],data;
}t[N*S];
inline void insert(int pl,int val){
	int x=root[pl-1];int y=root[pl]=++cnt;
	for(int i=S-1;i>=0;i--){
		int now=((val>>i)&1);
		t[y].ch[!now]=t[x].ch[!now];
		t[y].ch[now]=++cnt;
		y=t[y].ch[now],x=t[x].ch[now];
		t[y].data=pl;
	}
}
inline int work(int l,int x,int val){
	int an=0;
	for(int i=S-1;i>=0;i--){
		an<<=1;int now=((val>>i)&1);
		int want=t[x].ch[!now];
		if(want!=0&&t[want].data>=l)an++,x=want;
		else x=t[x].ch[now];
	}
	return an;
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	int s1,s2,s3,num=0,all=0;
	insert(++num,0);
	while(m--){read(s1);all^=s1;insert(++num,all);}
	while(n--){
		if(op()){read(s1);all^=s1;insert(++num,all);}
		else{
			read(s1);read(s2);read(s3);
			printf("%d\n",work(s1,root[s2],all^s3));
		}
	}
	
	return 0;
}
posted @ 2022-04-09 15:36  Feyn618  阅读(66)  评论(0编辑  收藏  举报