codeforces 817E 字典树计数



  •  (1 ≤ pi ≤ 108) — one warrior with personality pi joins Vova's army;
  • pi (1 ≤ pi ≤ 108) — one warrior with personality pi leaves Vova's army (it is guaranteed that there is at least one such warrior in Vova's army by this moment);
  • pi li (1 ≤ pi, li ≤ 108) — Vova tries to hire a commander with personality piand leadership li. There is at least one event of this type.
Output

For each event of the third type print one integer — the number of warriors whorespect the commander Vova tries to hire in the event.

Example
Input
5
1 3
1 4
3 6 3
2 4
3 6 3
Output
1
0
Note

In the example the army consists of two warriors with personalities 3 and 4 after first two events. Then Vova tries to hire a commander with personality 6 and leadership 3, and only one warrior respects him (, and 2 < 3, but , and 5 ≥ 3). Then warrior with personality 4 leaves, and when Vova tries to hire that commander again, there are no warriors who respect him.


  
  

题意

有一个军队,每个人都有一个个性值,主角时不时会增加、或者移除一个指定个性值的战士,也可能试图添加一个指挥官。指挥官有两个属性,分别为个性值和领导力,如果一个现役战士的个性值与指挥官的个性值的异或小于领导力,那么这个战士会敬重该指挥官。

有n次操作,如果是试图添加指挥官的操作,要求输出现役战士中有多少人会敬重这位指挥官。

作者:MoorLi 链接:http://www.jianshu.com/p/a24a9a3c6a11 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


一开始的想法是把这个题简单化,如果单纯是统计比一个数小的所有的数,用字典树可以很容易的做到,每次跟着这个数走,如果这个数==1,那么把0的这个分支的数目全部统计上,但是这里加上了一个异或,对于一组数的异或的二进制的所有情况,必须一一对应异或,但是我们需要的只不过是小于l的数目统计,所以我们可以大胆的贪心,跟着l在字典树上走,当这一位是1时,统计这个位为0的数目,运用虚树的思想,这棵被异或的树我们不用建出来,这一位要走1,那么我们就走和 d不同的方向,否则就走和 d相同的方向,加上统计即可。
1A hahaha


#include <bits/stdc++.h>
using namespace std;

int nxt[100010*31][2];
int sum[100010*31];
int qu[32];
int qu2[32];
int tot;
void insert(int x,int val)
{
	int p=0;
	for(int i=30;i>=0;i--)
	{
		int go=(x>>i)&1;
		if(!nxt[p][go]) nxt[p][go]=++tot;
		sum[p]+=val;
		p=nxt[p][go];
	}
	sum[p]+=val;
}

int ans;


void query()
{
	int p=0;
	for(int i=30;i>=0;i--)
	{
		if(qu2[i]==1)
		{
			if(nxt[p][qu[i]]!=0)
			ans+=sum[nxt[p][qu[i]]];
			if(!nxt[p][1-qu[i]]) return ;
			p=nxt[p][1-qu[i]];
		}
		else
		{
			if(!nxt[p][qu[i]]) return ;
		 	p=nxt[p][qu[i]];
		}
	}
}

int main()
{
	int q;
	scanf("%d",&q);
	tot=0;
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int x;
			scanf("%d",&x);
			insert(x,1);
		}
		else if(op==2)
		{
			int x;
			scanf("%d",&x);
			insert(x,-1);
		}
		else 
		{
			ans=0;
			int p,l;
			scanf("%d%d",&p,&l);
			for(int i=30;i>=0;i--)
				qu[i]=(p>>i)&1,qu2[i]=(l>>i)&1;

			query();
			printf("%d\n",ans );
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值