前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【cf842D】Vitya and Strange Lesson(01字典树)

【cf842D】Vitya and Strange Lesson(01字典树)

作者头像
饶文津
发布2020-06-02 15:58:15
4380
发布2020-06-02 15:58:15
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏

D. Vitya and Strange Lesson

题意

数列里有n个数,m次操作,每次给x,让n个数都异或上x。并输出数列的mex值。

题解

01字典树保存每个节点下面有几个数,然后当前总异或的是sw,则sw为1的位的节点左右孩子交换(不用真的交换)。左孩子的值小于左边总节点数则mex在左子树,否则在右子树。

代码

代码语言:javascript
复制
const int N=531000;//3e5<2^19<N
int sw=0;
struct Trie{
	int ch[N*20][2];
	int cnt[N*20];
	int size;
	void Build(int node, int pos){
		if(pos<0)return;
		rep(i,0,2){
			ch[node][i]=++size;
			cnt[size]=0;
			Build(ch[node][i], pos-1);
		}
	}
	void Init(){
		size=0;
		Build(0,19);
	}
	void Insert(int node, int pos, int num){
		if(pos<0)cnt[node]=1;
		if(pos<0) return;
		Insert(ch[node][(num>>pos)&1], pos-1, num);
		cnt[node]=cnt[ch[node][0]]+cnt[ch[node][1]];
	}
	int Query(int node, int pos, int num){
		if(pos<0)
			return num;
		int lson=(sw&(1<<pos))?1:0;
		if(cnt[ch[node][lson]]<(1<<pos)){
			return Query(ch[node][lson], pos-1, num);
		}
		return Query(ch[node][!lson], pos-1,num+(1<<pos));
	}
}trie;
int main() {
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		trie.Init();
		sw=0;
		rep(i,0,n){
			int x;
			scanf("%d",&x);
			trie.Insert(0,19,x);
		}
		while(m--){
			int x;
			scanf("%d",&x);
			sw^=x;
			printf("%d\n",trie.Query(0,19,0));
		}
		puts("");
	}
	return 0;
}

自从用了cf上偷来的开头模板以后,感觉写代码速度也快了。但是,代码像裙子越短越性感。所以博客上就不放头文件了。 其实可以像线段树一样写,写得更短了哈哈:

代码语言:javascript
复制
const int N=531000;
int sw=0;
struct Trie{
	int cnt[N*20];
	void Insert(int node, int pos, int num){
		if(pos<0){cnt[node]=1;return;}
		Insert(node<<1|((num>>pos)&1), pos-1, num);
		cnt[node]=cnt[node<<1]+cnt[node<<1|1];
	}
	int Query(int node, int pos, int num){
		if(pos<0) return num;
		int cur=(sw>>pos)&1;
		cur|=node<<1;
		if(cnt[cur]<(1<<pos)) return Query(cur, pos-1, num);
		return Query(cur^1, pos-1,num+(1<<pos));
	}
}trie;
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	rep(i,0,n){
		int x;
		scanf("%d",&x);
		trie.Insert(1,19,x);
	}
	while(m--){
		int x;
		scanf("%d",&x);
		sw^=x;
		printf("%d\n",trie.Query(1,19,0));
	}
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-08-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题意
  • 题解
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档