cunzai_zsy0531

关注我

P4735 最大异或和 题解

题面

考虑异或可以表示成前缀和的形式,则 \(a[p]\oplus a[p+1]\oplus\ldots \oplus a[n]\oplus x=s[p-1]\oplus s[n] \oplus x\)。后面都是知道的,所以可以拿着 \(s[n]\oplus x\) 的值去01-trie上做匹配。注意到还有一个 \(p\in[l-1,r-1]\) 的限制,可以使用可持久化trie,查询第 \(r-1\) 个版本,再在每个节点记录一个 \(las\) 表示走到这个点的 \(l\) 的最大值,只走其中 \(las\geq l-1\) 的即可。

点击查看代码
#include<iostream>
#include<cstdio>
using namespace std;
const int N=6e5+13,logN=21;
int n,m,s[N],rt[N];
struct Trie{
	int ch[N*logN][2],cnt,las[N*logN];
	inline int insert(int num){
		int now=rt[num-1],root=++cnt,p=root;las[p]=num;
		for(int i=24;i>=0;--i){
			int c=(s[num]&(1<<i)?1:0);
			ch[p][c^1]=ch[now][c^1];ch[p][c]=++cnt;
			p=cnt,now=ch[now][c];las[p]=num;
		}
		return root;
	}
	inline int query(int l,int r,int x){
		int p=rt[r];int res=0;
		if(!r) return x;
		for(int i=24;i>=0;--i){
			int c=(x&(1<<i)?1:0);
			if(ch[p][c^1]&&las[ch[p][c^1]]>=l) p=ch[p][c^1],res+=(1<<i);
			else p=ch[p][c];
		}
		return res;
	}
}T;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&s[i]);
		s[i]^=s[i-1];
		rt[i]=T.insert(i);
	}
	while(m--){
		char op;int l,r,x;
		cin>>op;
		if(op=='A'){
			scanf("%d",&s[++n]);
			s[n]^=s[n-1];
			rt[n]=T.insert(n);
		}
		else{
			scanf("%d%d%d",&l,&r,&x);
			printf("%d\n",T.query(l-1,r-1,s[n]^x));
		}
	}
	return 0;
}
posted @ 2022-05-19 16:28  cunzai_zsy0531  阅读(16)  评论(0编辑  收藏  举报