Description
比特集合是一种抽象数据类型(Abstract Data Type) ,其包含一个集合S,并支持如下几种操作:
INS M : 将元素 M 插入到集合S中;
DEL M : 将集合S中所有等于 M 的元素删除;
ADD M : 将集合S中的所有元素都增加数值M ;
QBIT k : 查询集合中有多少个元素满足其二进制的第 k位为 1 。
初始时,集合S为空集。请实现一个比特集合,并对于所有的QBIT操作输出相应的答案。
Input
输入第一行包含一个正整数N,表示操作的数目。
接下来N行,每行为一个操作,格式见问题描述。
Output
对于每一个QBIT操作,输出一行,表示相应的答案。
Sample Input
8
INS 1
QBIT 0
ADD 1
QBIT 0
QBIT 1
DEL 2
INS 1
QBIT 1
Sample Output
1
0
1
0
HINT
数据规模和约定
时间限制2s。
对于30%的数据,1 ≤ N ≤ 10000。
对于100%的数据,1 ≤ N ≤ 500000;QBIT操作中的k满足, 0 ≤ k < 16。INS/DEL操作中,满足0 ≤ M ≤ 10^9;ADD操作中, 满足0 ≤ M ≤ 1000。
注意
注意集合S可以包含多个重复元素。
Source
2012国家集训队Round 1 day4
建BIT,c[k][x]表示二进制后k位小于等于x的数的个数.
则询问即查询
c[k][2k+1−1]−c[k][2k−1]
单独开个数记录下add操作的影响.
容易产生逻辑混乱.
拒绝接受关于这题的QQ问答T_T
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define MAXN 500010
#define GET (ch >= '0' && ch <= '9')
#define lowbit(x) (x & -x)
using namespace std;
const int N = 1 << 16;
int n,x,sum;
char ch[5];
multiset<int> s;
int c[16][1 << 16];
void in(int &x)
{
char ch = getchar() ; x = 0;
while (!GET) ch = getchar();
while (GET) x = x * 10 + ch - '0' , ch = getchar();
}
inline void add(int t,int x,int delta) { for ( ; x <= N ; x += lowbit(x)) c[t][x] += delta; }
inline int query(int t,int x)
{
int ret = 0;
for ( ; x ; x -= lowbit(x)) ret += c[t][x];
return ret;
}
int main()
{
for (in(n) ; n ; n--)
{
scanf("%s",ch) ; in(x);
if (ch[0] == 'A') sum += x;
if (ch[0] == 'I')
{
s.insert(x - sum);
for (int i = 1 ; i <= 16 ; i++) add(i - 1 , (((1 << i) - 1) & (x - sum)) + 1 , 1);
}
if (ch[0] == 'D')
{
int t = s.count(x - sum) ; s.erase(x - sum);
for (int i = 1 ; i <= 16 ; i++) add(i - 1 , (((1 << i) - 1) & (x - sum)) + 1 , -t);
}
if (ch[0] == 'Q')
{
int l = 1 << x , r = (1 << (x + 1)) - 1 , ans = 0;
ans += query(x , min( max( r - ( sum & ( (1 << (x + 1)) - 1) ) + 1 , 0 ) , 1 << 16 ) );
ans -= query(x , min( max( l - ( sum & ( (1 << (x + 1)) - 1) ) , 0 ) , 1 << 16));
l += 1 << (x + 1) , r += 1 << (x + 1);
ans += query(x , min( max( r - ( sum & ( (1 << (x + 1)) - 1) ) + 1 , 0 ) , 1 << 16 ));
ans -= query(x , min( max( l - ( sum & ( (1 << (x + 1)) - 1) ) , 0 ) , 1 << 16 ) );
printf("%d\n", ans);
}
}
}