样例数据
输入
7
add 11
cnt 15
add 4
add 0
cnt 6
del 4
cnt 15
输出
1
2
2
分析:这是我第一次做分块的题,一般是要么预处理复杂度高而查询复杂度低、要么预处理复杂度低而查询复杂度高的题目,不妨就分成
√
n块分别处理(想想均值不等式,都是在相等时取最小值嘛),本题的s有
216
,所以分成
28
块(根据前8位),每块
28
个(根据后8位)。
100分代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int Maxn=(1<<8);//这个数就是256啦,你直接写也可以
inline int read()
{
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
return i*f;
}
int n,a[Maxn+50][Maxn+50];//第一维存前八位,第二维存后八位
char ch[5];
int main()
{
n=read();
while(n--)
{
scanf("%s",ch+1);
int s=read();
int t=s>>8,res=s-(t<<8);//t得到前八位,res就得到后八位(也可以s=t&255)
switch(ch[1])
{
case 'a'://加数
{
for(int i=0;i<Maxn;i++)//根据前8位与运算决定分到哪一块(只要与运算等于本身就要加进这个块)
{
if((t&i)==t)a[i][res]++;//在这一块后八位是res的地方+1
}
break;
}
case 'c'://查询
{
int r=0;
for(int i=0;i<Maxn;i++)//只需查询后八位(因为直接把前八位的t放在一维就是所有前八位已经满足了的,只需后八位也满足,就可以满足a&s==a)
{
if((i&res)==i)r+=a[t][i];
}
cout<<r<<endl;
break;
}
case 'd'://删数(和加数相同,只是--罢了)
{
for(int i=0;i<Maxn;i++)
{
if((t&i)==t)a[i][res]--;
}
break;
}
}
}
return 0;
}
本题结。