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
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
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 }