zoukankan      html  css  js  c++  java
  • 【cf842D】Vitya and Strange Lesson(01字典树)

    D. Vitya and Strange Lesson

    题意

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

    题解

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

    代码

    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
    ",trie.Query(0,19,0));
    		}
    		puts("");
    	}
    	return 0;
    }
    

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

    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
    ",trie.Query(1,19,0));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Centos7配置局域网yum源报错——Error downloading packages: failed to retrieve packages...
    Centos7扩展根分区——不增加磁盘
    Paxos算法
    记一次业务中的大坑-MYSQL有重复数据下的增加主键
    填坑之路——Hadoop分布式缓存
    Java接口技术
    Java-IO操作性能对比
    Clob对象转换为String
    剖析Reflection.getCallerClass
    Java类的加载、链接和初始化
  • 原文地址:https://www.cnblogs.com/flipped/p/7456196.html
Copyright © 2011-2022 走看看