【乱搞】BZOJ3578 GTY的人类基因组计划2

题面在这里

给每个人赋一个随机编号,一个集合的hash值就是xor和

用map记录哪些集合被统计过,set维护可能产生答案的房间

询问时暴力删除即可,因为集合数是\(O(q)\)

示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<algorithm>
using namespace std;

const int maxn=100005;
int N,n,q,w[maxn],a[maxn],where[maxn],num[maxn];
#define brand() ((rand()<<16)|(rand()<<1)|(rand()&1))
map<int,bool> usd;
set<int> S;
char s[20];
int main(){
srand(998244353);
scanf("%d%d%d",&N,&n,&q);
for (int i=1;i<=N;i++) w[i]=brand(),a[where[i]=1]^=w[i];
S.insert(1);num[1]=N;
while (q--){
scanf("%s",s);
if (s[0]=='C'){
int x,y;scanf("%d%d",&x,&y);
S.erase(where[x]);S.erase(y);
a[where[x]]^=w[x]; a[y]^=w[x];
if (!usd[a[where[x]]]) S.insert(where[x]);
if (!usd[a[y]]) S.insert(y);
num[where[x]]--;num[y]++; where[x]=y;
}else{
int l,r;scanf("%d%d",&l,&r);
set<int>::iterator it=S.lower_bound(l);
int res=0;
while (it!=S.end()&&(*it)<=r){
res+=num[*it];
usd[a[*it]]=1;
S.erase(it);
it=S.lower_bound(l);
}
printf("%d\n",res);
}
}
return 0;
}