zoukankan      html  css  js  c++  java
  • 【题解】CF817E Choosing The Commander

    题目戳我

    ( ext{Solution:})

    看到异或(以及E题的位置)想到(01Trie.)

    考虑维护一个(sum)数组代表树上(x)点内有多少数字。那么添加操作每次走一个二进制位的时候更新(sum+1,)删除时更新(sum-1.)

    考虑如何询问:

    先读好题,上面说的是异或(p_i)小于(l_i)

    所以这里(l_i)的二进制位起到了最主要的限制作用。

    (l_i)的这一位是(1,)则我们加上(p_i)这一位所对应相同的节点的(sum)(保证异或这一位是(0,)小于(l_i)

    (l_i)的这一位是(0)也就没有必要累加答案了,因为这里只有一种异或法则:令这一位为(0.)

    考虑继续走:若(l_i)这一位是(0)我们就可以走到异或(p_i)这一位为(0)的位置;反之,由于我们之前计算过贡献,所以我们走到异或(p_i)这一位为(1)的位置。

    时间复杂度(O(nlog 10^8).)

    #include<bits/stdc++.h>
    using namespace std;
    int Q,T[3000010][2],n;
    int tot=1,sum[3000010];
    inline void insert(int v,int vv){
    	int p=1;
    	for(int i=30;i>=0;--i){
    		int x=v>>i&1;
    		sum[p]+=vv;
    		if(!T[p][x])T[p][x]=++tot;
    		p=T[p][x];
    	}
    	sum[p]+=vv;
    }
    int query(int ch,int v){
    	int ans=0,p=1;
    	for(int i=30;i>=0;--i){
    		int vp=v>>i&1;
    		int chp=ch>>i&1;
    		if(chp<vp)ans+=sum[T[p][0]];
    		if(vp&&chp)ans+=sum[T[p][1]];
    		if(!vp)p=T[p][chp];
    		else p=T[p][chp^1];
    	}
    	return ans;
    }
    int main(){
    	scanf("%d",&n);
    	while(n--){
    		int x,y,z;
    		scanf("%d%d",&x,&y);
    		if(x==1)insert(y,1);
    		if(x==2)insert(y,-1);
    		if(x==3){
    			scanf("%d",&z);
    			printf("%d
    ",query(y,z));
    		}
    	}
    	return 0;
    }
    

    注意事项:(Trie)最好以(1)为根,有时候会出现一些不知道什么鬼的错误)

  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/h-lka/p/14043338.html
Copyright © 2011-2022 走看看