可持久化trie入门

版权声明:小蒟蒻的博客转载也请注明出处哦 https://blog.csdn.net/qq_42835823/article/details/86656499

初步认识:处理trie树上的异或(xor)问题



bzoj3261 最大异或和

推荐题解

注意:

  • s u m [   ] sum[ ] 记录的是经过这个点的次数
  • s u m [ s o n [ y ] [ ! p ] ] s u m [ s o n [ x ] [ ! p ] ] > 0 sum[son[y][!p]]-sum[son[x][!p]]>0 表示查询区间内有这样的一个数
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5,inf=2e9,M=14400005;
int sum[M],son[M][2],rt[M],tot=0;
void build(int x,int &y,int v,int d){
	sum[y=++tot]=sum[x]+1;//走过一遍加一 
	if(d<0)return;
	int p=(v>>d)&1;
	son[y][p^1]=son[x][p^1];
	build(son[x][p],son[y][p],v,d-1);
}
int query(int x,int y,int v,int d){
	if(d<0)return 0;
	int p=(v>>d)&1;int tmp=sum[son[y][p^1]]-sum[son[x][p^1]];//查询区间内是否有这样的一个数 
	if(tmp>0)return (1<<d)+query(son[x][p^1],son[y][p^1],v,d-1);
	else return query(son[x][p],son[y][p],v,d-1);
}
int n,m,all;
int main(){
	scanf("%d%d",&n,&m);
	build(rt[0],rt[1],0,24);
	n++;
	for(int i=2;i<=n;i++){
		int x;
		scanf("%d",&x);
		all^=x;/////////////
		build(rt[i-1],rt[i],all,24);
	}
	char s[5];
	while(m--){
		scanf("%s",s+1);
		if(s[1]=='A'){
			int x;
			scanf("%d",&x);
			all^=x;
			build(rt[n],rt[n+1],all,24);
			n++;
		}
		else{
			int x,y,k;
			scanf("%d%d%d",&x,&y,&k);
			printf("%d\n",query(rt[x-1],rt[y],k^all,24));//sum[n] xor sum[p - 1] xor x
		}
	}
	return 0;
}

loj6144 可持久化数据结构

W O J 4347 WOJ4347

推荐题解

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5,M=2050100;
int n,m,a[N],sand=0x7fffffff,sor=0,same[40],xortag=0,opt[40],rt[N];
int son[M][2],siz[M],tot;
void insert(int x,int y,int v){
	for(int i=30;~i;i--){
		bool f=same[i]?0:((v>>i)&1);
		siz[y]=siz[x]+1;
		son[y][f^1]=son[x][f^1];
		y=son[y][f]=++tot;
		x=son[x][f];
	}
	siz[y]=siz[x]+1;
}
void build(){
	memset(siz,0,sizeof(siz));
	memset(son,0,sizeof(son));
	memset(rt,0,sizeof(rt));
	rt[0]=tot=1;
	insert(0,rt[0],0);
	for(int i=1;i<=n;i++){
		rt[i]=++tot;
		insert(rt[i-1],rt[i],a[i]);
	}
}
int query(int l,int r,int k){
	int ans=0;
	for(int i=30;~i;i--){
		if(same[i]){
			ans+=opt[i]<<i;
			l=son[l][0];
			r=son[r][0];
			continue;
		}
		bool f=xortag&(1<<i);
		int sum=siz[son[r][f]]-siz[son[l][f]];
		if(sum>=k){
			l=son[l][f];
			r=son[r][f];
		}
		else{
			k-=sum;
			ans+=1<<i;
			l=son[l][f^1];
			r=son[r][f^1];
		}
	}
	return ans;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		sand&=a[i];
		sor|=a[i];
	}
	for(int i=0;i<=30;i++)
		same[i]=((sand>>i)&1)==((sor>>i)&1);//
	build();
	char s[10];int x;
	while(m--){
		scanf("%s",s+1);
		if(s[1]=='X'){
			scanf("%d",&x);
			xortag^=x;//记录,查询时再修改 
			for(int i=0;i<=30;i++)
				if(same[i]&&(x&(1<<i)))opt[i]^=1;// 
		}
		if(s[2]=='n'){
			scanf("%d",&x);
			int flag=0;
			for(int i=0;i<=30;i++)
				if(!(x&(1<<i)))
					if(same[i])opt[i]=0;
					else{
						flag=1;
						opt[i]=0;
						same[i]=1;//
					}
			if(flag)build();//重构 
		}
		if(s[1]=='O'){
			scanf("%d",&x);
			int flag=0;
			for(int i=0;i<=30;i++)
				if(x&(1<<i))
					if(same[i])opt[i]=1;
					else{
						flag=1;
						opt[i]=1;
						same[i]=1;
					}
			if(flag)build();
		}
		if(s[2]=='s'){
			int l,r;
			scanf("%d%d%d",&l,&r,&x);
			printf("%d\n",query(rt[l-1],rt[r],x));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835823/article/details/86656499