10月3日NOIP-模拟T3 subset

3.1 题目᧿述
一开始你有一个空集,集合可以出现重复元素,然后有Q个操作

  1. add s
    在集合中加入数字s。
  2. del s
    在集合中删除数字s。保证s存在
  3. cnt s
    查询满足a&s=a条件的a的个数
    3.2 输入Ṭᔿ
    第一行一个整数Q接下来Q行,每一行都是3个操作中的一个
    3.3 输出Ṭᔿ
    对于每个cnt操作输出答案

恩…这道题首先暴力很好想,就每加入一个数后从0枚举到216更新答案,查询时O(1)查询就可以了(没试过暴力,这样应该没错吧…)然后很明显要T飞的。然后这种做法明显是通法,也就是说无论什么要求都可以这样做,但这道题是要求a&s=a,便去找这个式子有什么特殊的地方。然后发现如果把a,s换为二进制,a&s=a相当于任意对应的几位&后都不变,然后就可以分块来做,直接分为28块,发现时间复杂度瞬间降了下来,,每次把加入(删掉)的数依次看是否丢入(取出)块中。在询问中直接进入询问数a的前八位对应的块,在块里枚举,对应第二维ed。 那这道题就可以偷税的A了

code871

#include<bits/stdc++.h>
using namespace std;
int n,f[300][300],x,op,ed;
string saber;
int Read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))
    {
    	if(ch=='-') f=-1;
    	ch=getchar();
    }
    while(isdigit(ch))
    {
    	x=(x<<1)+(x<<3)+ch-'0';
    	ch=getchar();
    }
    return f*x;
}
int main()
{
	n=Read();
	for(int i=1;i<=n;i++)
	{
		cin>>saber;
		x=Read();
		op=x>>8;
		ed=x&255;
		if(saber[0]=='a')
		{
			for(int i=0;i<=255;i++)
			if((op&i)==op) f[i][ed]+=1;
		}
		if(saber[0]=='d')
		{
			for(int i=0;i<=255;i++)
			if((op&i)==op) f[i][ed]-=1;
		}
		if(saber[0]=='c')
		{
			int ans=0;
			for(int i=0;i<=255;i++)
			if((i&ed)==i) ans+=f[op][i];
			printf("%d\n",ans);
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值