BZOJ3578:GTY的人类基因组计划2(集合hash,STL)

Description

  GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信息点数,点数为房间里的人数,如果一个房间里的一群人已经做过实验了那么这些人将不会增加实验信息点数(不会增加是针对这一群人的,不是对这群人中的每个人,即1,2,3做了实验,1,2再做实验还会增加2点实验点数)

Input

第一行两个整数n,m,q(n,m,q<=10^5)表示人数,房间数和操作数
接下来q行每行一个操作 "C i j"表示让第i个人去房间j "W l r" 表示让区间[l,r]的房间做实验

Output

对于每一个W操作,输出一个数,表示此次操作所获得的实验点数

Sample Input

3 5 7
C 1 2
C 2 2
W 1 2
C 3 2
W 1 2
C 3 3
W 1 3

Sample Output

3
3
0

HINT

善用STL

Solution

集合$hash$,就是对每个元素$rand$一个$long~long$范围以内的数异或起来。

这个题可以用数组维护一下每个房间的异或值,每个房间人的数量,每个人的位置,

用$set$维护一下当前可以贡献答案的房间号,

用$map$维护一下某个$hash$值是否出现过。

修改的话就修改两个房间的信息,查询的话就在$set$里查询,同时把查询后的房间号从$set$里删掉。

$set$内的每个元素最多被遍历一次,遍历到了就得被删除,而往$set$里插入的数字是$O(n)$级别的,复杂度合法。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<map>
 6 #include<set>
 7 #define N (100009)
 8 #define LL long long
 9 using namespace std;
10 
11 int n,m,q,l,r,num[N],pos[N],ans;
12 LL val[N],XOR[N];
13 set<int>s;
14 set<int>::iterator it;
15 map<LL,bool>vis;
16 
17 inline int read()
18 {
19     int x=0,w=1; char c=getchar();
20     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
21     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
22     return x*w;
23 }
24 
25 int main()
26 {
27     n=read(); m=read(); q=read();
28     for (int i=1; i<=n; ++i)
29         pos[i]=1, val[i]=(((LL)rand()<<16)|rand()), XOR[1]^=val[i];
30     num[1]=n; s.insert(1);
31     for (int i=1; i<=q; ++i)
32     {
33         char opt=getchar();
34         while (opt<'A' || opt>'Z') opt=getchar();
35         l=read(); r=read();
36         if (opt=='C')
37         {
38             if (pos[l]==r) continue;
39             s.erase(pos[l]); s.erase(r);
40             XOR[pos[l]]^=val[l]; num[pos[l]]--;
41             if (!vis[XOR[pos[l]]]) s.insert(pos[l]);
42             pos[l]=r; XOR[r]^=val[l]; num[r]++;
43             if (!vis[XOR[r]]) s.insert(r);
44         }
45         else
46         {
47             ans=0;
48             for (it=s.lower_bound(l); it!=s.end() && *it<=r; it=s.lower_bound(l))
49                 vis[XOR[*it]]=1, ans+=num[*it], s.erase(it);
50             printf("%d\n",ans);
51         }
52     }
53 }

转载于:https://www.cnblogs.com/refun/p/10392630.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值