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)为根,有时候会出现一些不知道什么鬼的错误)

  • 相关阅读:
    Day 09 函数
    Day 09 作业
    Day 08 可变与不可变对象/列表与字典内置方法
    Day 08 作业
    Day 07 字符串内置方法和爬虫基础3
    Day 06 流程控制和爬虫基础2
    Day 05 文本处理和爬虫基础1
    Day 04 作业
    Day 04 数据类型基础
    Day 03 Python 基础
  • 原文地址:https://www.cnblogs.com/h-lka/p/14043338.html
Copyright © 2011-2022 走看看