题目描述
GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信息点数,点数为房间里的人数,如果一个房间里的一群人已经做过实验了那么这些人将不会增加实验信息点数(不会增加是针对这一群人的,不是对这群人中的每个人,即1,2,3做了实验,1,2再做实验还会增加2点实验点数)
输入格式
第一行两个整数n,m,q(n,m,q<=10^5)表示人数,房间数和操作数
接下来q行每行一个操作 "C i j"表示让第i个人去房间j "W l r" 表示让区间[l,r]的房间做实验
输出格式
对于每一个W操作,输出一个数,表示此次操作所获得的实验点数
输入输出样例
输入 #1
3 5 7 C 1 2 C 2 2 W 1 2 C 3 2 W 1 2 C 3 3 W 1 3
输出 #1
View Code
3 3 0
hash 异或操作来表明房间的人(显然异或两次说明人走了)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ///////////////////////////////////// const int N=1e5+100; set<int>s; map<unsigned long long,bool>mp; unsigned long long num[N],n,m,q,room[N],siz[N],in[N]; int main() { srand(2019+8+26); scanf("%d%d%d",&n,&m,&q); rep(i,1,n) { in[i]=1; int k1=rand()<<16|rand()%1000000000, k2=rand()<<16|rand()%2000000000; num[i]=k1*k2; } s.insert(1); rep(i,1,n)room[1]^=num[i]; siz[1]=n; while(q--) { char s2[2];int x,y; scanf("%s%d%d",s2,&x,&y); if(s2[0]=='C') { if(in[x]==y)continue; s.erase(in[x]);s.erase(y); room[in[x]]^=num[x];room[y]^=num[x]; if(!mp[room[in[x]]])s.insert(in[x]); if(!mp[room[y]])s.insert(y); siz[in[x]]--;siz[y]++; in[x]=y; } else if(s2[0]=='W') { auto it=s.lower_bound(x);int ans=0; while(it!=s.end()&&*it<=y) { ans+=siz[*it]; mp[room[*it]]=1; s.erase(*it); it=s.lower_bound(x); } printf("%d ",ans); } } return 0; }