01trie

同trie,只是维护的字符只有0和1

可以通过每次如果可以选择不同字符则选择不同字符的贪心思想维护最大异或和。多用于解决异或问题。

为什么上面那样操作可以维护最大异或和?因为我们按照从高位往底的顺序,如果当前答案这一位异或得1,其他答案的更高位都不超过当前答案的更高位,且其他答案这一位异或得0,那么当前答案必定是最大的。

答案得到的是所有加入到trie中的数中的一个与 num 异或得到的最大值。

如果维护多个,可以前缀和+可持久化线段树。

举个例子:3=(011)2<4=(100)2

代码实现:

void ins(int num){
	int p=0;
	for(int i=30;i>=0;--i){
		int c=((num>>i)&1);
		if(!ch[p][c]) ch[p][c]=++tot;
		p=ch[p][c];
	}
}
int find(int num){
	int p=0,ans=0;
	for(int i=30;i>=0;--i){
		int c=((num>>i)&1);
		if(ch[p][c^1]){
			ans+=(1<<i);
			p=ch[p][c^1];
		}else p=ch[p][c];
	}
	return ans;
}

最长异或路径

最大异或和

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define db double
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define sky fflush(stdout);
#define gc getchar
#define pc putchar
namespace IO{
	inline bool blank(char c){
		return c==' ' or c=='\n' or c=='\t' or c=='\r' or c==EOF;
	}
	inline void gs(char *s){
		char ch=gc();
		while(blank(ch) ) {ch=gc();}
		while(!blank(ch) ) {*s++=ch;ch=gc();}
		*s=0;
	}
	inline void gs(std::string &s){
		char ch=gc();s+='#';
		while(blank(ch) ) {ch=gc();}
		while(!blank(ch) ) {s+=ch;ch=gc();}
	}
	inline void ps(char *s){
		while(*s!=0) pc(*s++);
	}
	inline void ps(const std::string &s){
		for(auto it:s) 
			if(it!='#') pc(it);
	}
	template<class T>
	inline void read(T &s){
		s=0;char ch=gc();bool f=0;
		while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
		while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
		if(ch=='.'){
			db p=0.1;ch=gc();
			while('0'<=ch&&ch<='9') {s=s+p*(ch^48);ch=gc();}
		}
		s=f?-s:s;
	}
	template<class T,class ...A>
	inline void read(T &s,A &...a){
		read(s);read(a...);
	}
};
using IO::read;
using IO::gs;
using IO::ps;
int n,Q;
const int N=3e5+3;
const int S=6e5+3;
struct trie{
	int ch[S*32][2],tot;
	int val[S*32],rt[S];
	inline void ins(int p,int lp,int x){
		for(int i=30;i>=0;--i){
			int c=(x>>i)&1;
			val[p]=val[lp]+1;
			if(!ch[p][c]) ch[p][c]=++tot;
			ch[p][c^1]=ch[lp][c^1];
			p=ch[p][c];
			lp=ch[lp][c];
		}
		val[p]=val[lp]+1;
	}
	inline int find(int p,int lp,int x){
		int res=0;
		for(int i=30;i>=0;--i){
			int c=(x>>i)&1;
			if(val[ch[p][c^1] ]-val[ch[lp][c^1] ]){
				res|=(1<<i);
				p=ch[p][c^1];
				lp=ch[lp][c^1];
			}else{
				p=ch[p][c];
				lp=ch[lp][c];
			}
		}
		return res;
	}
}t;
int main(){
	//filein(a);fileot(a);
	read(n,Q);
	int sum=0;
	t.rt[1]=++t.tot;
	t.ins(t.rt[1],t.rt[0],0);
	for(int i=1;i<=n;++i){
		int x; read(x); sum^=x;
		t.rt[i+1]=++t.tot;
		t.ins(t.rt[i+1],t.rt[i],sum);
	}
	int i=n;
	while(Q--){
		char op=gc();
		while(IO::blank(op) ) op=gc();
		if(op=='A'){
			int x; read(x); sum^=x;
			t.rt[++i+1]=++t.tot;
			t.ins(t.rt[i+1],t.rt[i],sum);
		}else if(op=='Q'){
			int l,r,x; read(l,r,x);
			printf("%d\n",t.find(t.rt[r],t.rt[std::max(0,l-1)],x^sum) );
		}
	}
	return 0;
}

posted @   cbdsopa  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示