bzoj2568 比特集合
Description
比特集合是一种抽象数据类型(Abstract Data Type) ,其包含一个集合S,并支持如下几种操作:
INS M : 将元素 M 插入到集合S中;
DEL M : 将集合S中所有等于 M 的元素删除;
ADD M : 将集合S中的所有元素都增加数值M ;
QBIT k : 查询集合中有多少个元素满足其二进制的第 k位为 1 。
初始时,集合S为空集。请实现一个比特集合,并对于所有的QBIT操作输出相应的答案。
INS M : 将元素 M 插入到集合S中;
DEL M : 将集合S中所有等于 M 的元素删除;
ADD M : 将集合S中的所有元素都增加数值M ;
QBIT k : 查询集合中有多少个元素满足其二进制的第 k位为 1 。
初始时,集合S为空集。请实现一个比特集合,并对于所有的QBIT操作输出相应的答案。
Input
输入第一行包含一个正整数N,表示操作的数目。
接下来N行,每行为一个操作,格式见问题描述。
接下来N行,每行为一个操作,格式见问题描述。
Output
对于每一个QBIT操作,输出一行,表示相应的答案。
Sample Input
8
INS 1
QBIT 0
ADD 1
QBIT 0
QBIT 1
DEL 2
INS 1
QBIT 1
INS 1
QBIT 0
ADD 1
QBIT 0
QBIT 1
DEL 2
INS 1
QBIT 1
Sample Output
1
0
1
0
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可以包含多个重复元素。
正解:树状数组。
维护$16$个树状数组,其中第$i$个表示每个数$ \mod 2^{i+1}$的数是什么。
插入删除直接在树状数组里面搞就行了,查询某个数的个数直接$hash$就行了。
区间加就直接对于每个树状数组记录目前的$0$在哪个位置,不对树状数组进行修改。
查询就直接在$2^{k+1}$的树状数组上查询$[2^{k},2^{k+1}-1]$的数有多少个就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define lb(x) (x & -x) 6 #define rhl (1253557) 7 8 using namespace std; 9 10 struct edge{ int nt,to,v; }g[1000010]; 11 12 int c[17][150010],bin[17],head[rhl+10],n,m,num; 13 char ch[5]; 14 15 il int gi(){ 16 RG int x=0,q=1; RG char ch=getchar(); 17 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 18 if (ch=='-') q=-1,ch=getchar(); 19 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 20 return q*x; 21 } 22 23 il void insert(RG int from,RG int to,RG int v){ 24 g[++num]=(edge){head[from],to,v},head[from]=num; return; 25 } 26 27 il void add(RG int id,RG int x,RG int v){ 28 for (;x<=bin[id+1];x+=lb(x)) c[id][x]+=v; return; 29 } 30 31 il int query(RG int id,RG int x){ 32 RG int res=0; for (;x;x-=lb(x)) res+=c[id][x]; return res; 33 } 34 35 il void hshadd(RG int x,RG int v){ 36 RG int wyh=(x%rhl+rhl)%rhl; 37 for (RG int i=head[wyh];i;i=g[i].nt) 38 if (g[i].to==x){ g[i].v+=v; return; } 39 insert(wyh,x,v); return; 40 } 41 42 il int hshquery(RG int x){ 43 RG int wyh=(x%rhl+rhl)%rhl; 44 for (RG int i=head[wyh];i;i=g[i].nt) 45 if (g[i].to==x) return g[i].v; 46 return 0; 47 } 48 49 int main(){ 50 #ifndef ONLINE_JUDGE 51 freopen("bit.in","r",stdin); 52 freopen("bit.out","w",stdout); 53 #endif 54 n=gi(),bin[0]=1; 55 for (RG int i=1;i<=16;++i) bin[i]=bin[i-1]<<1; 56 for (RG int i=1,x,k,l,r;i<=n;++i){ 57 scanf("%s",ch); 58 if (ch[0]=='I'){ 59 x=gi(); 60 for (RG int j=0,y;j<=15;++j){ 61 y=(x-m)%bin[j+1]; if (y<=0) y+=bin[j+1]; add(j,y,1); 62 } 63 hshadd(x-m,1); 64 } 65 if (ch[0]=='D'){ 66 x=gi(),k=hshquery(x-m); if (!k) continue; 67 for (RG int j=0,y;j<=15;++j){ 68 y=(x-m)%bin[j+1]; if (y<=0) y+=bin[j+1]; add(j,y,-k); 69 } 70 hshadd(x-m,-k); 71 } 72 if (ch[0]=='A') m+=gi(); 73 if (ch[0]=='Q'){ 74 k=gi(),l=(bin[k]-m)%bin[k+1],r=(bin[k+1]-1-m)%bin[k+1]; 75 if (l<=0) l+=bin[k+1]; if (r<=0) r+=bin[k+1]; 76 if (l<=r) printf("%d\n",query(k,r)-query(k,l-1)); 77 else printf("%d\n",query(k,r)-query(k,l-1)+query(k,bin[k+1])); 78 } 79 } 80 return 0; 81 }