BZOJ2568 [国家集训队2012]比特集合

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可以包含多个重复元素。

题解

首先我们可以发现整体加只是要维护一个标记cnt表示当前加了多少,那么add x->add (x - cnt), del x -> del (x - cnt), qbit k ->查询加cnt之后第k位为1的数的个数<=>查询后k位在$[2^k - cnt, 2^{k + 1} - 1 - cnt]$范围内的数。

令$c[i][j]$表示后$i$位小于等于$j$的数的个数,用树状数组维护,那么答案就是$num - c[i][2^k-1]$(没有计$cnt$的影响)。

附代码:

#include <algorithm>
#include <cstdio>
#include <set>
typedef long long LL;
const int mod = 1000000009;
inline int lowbit(int x) { return x & -x; }
const int N = 1 << 16;
int s[16][N];
void add(int a, int k, int x) {
  for (++k; k <= N; k += lowbit(k))
    s[a][k] += x;
}
int query(int a, int k) {
  int ans = 0;
  for (++k; k; k -= lowbit(k)) ans += s[a][k];
  return ans;
}
std::multiset<int> S;
int main() {
  int m, x, cnt = 0, num = 0;
  scanf("%d", &m);
  char s[10];
  while (m--) {
    scanf("%s%d", s, &x);
    if (*s == 'I') {
      ++num;
      S.insert(x -= cnt);
      for (int i = 0; i < 16; ++i) add(i, ((1 << (i + 1)) - 1) & x, 1);
    } else if (*s == 'D') {
      int l = S.count(x -= cnt);
      num -= l;
      S.erase(x);
      for (int i = 0; i < 16; ++i) add(i, ((1 << (i + 1)) - 1) & x, -l);
    } else if (*s == 'A') {
      cnt += x;
    } else {
      int r = ((1 << x) - cnt - 1) & ((1 << (x + 1)) - 1), l = (-cnt) & ((1 << (x + 1)) - 1);
      if (r >= l)
        printf("%d\n", num - query(x, r) + query(x, l - 1));
      else
        printf("%d\n", query(x, l - 1) - query(x, r));
    }
  }
  return 0;
}

  

posted @ 2017-08-09 16:25  _rqy  阅读(349)  评论(0编辑  收藏  举报