题目描述
题解
用一个set维护当前所有可以做实验的房间
对于每一坨人搞一个hash值(据说可以随机一些大整数,我用了一个S进制数胡搞)
然后用一个map记录一下每一个hash值是否出现过
当把一个人挪到另一个房间去的时候重新计算一下hash值,并维护set
upper_bound找到大于它的最小的
lower_bound找到大于等于它的最小的
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define UL unsigned long long
#define N 100005
const UL S=2000001001LL;
int n,m,q,ans;
int loc[N],cnt[N];
UL mi[N],hash[N];
set <int> s;
map <int,bool> mp;
int main()
{
scanf("%d%d%d",&n,&m,&q);
mi[0]=1;
for (int i=1;i<=n;++i)
{
mi[i]=mi[i-1]*S;
hash[1]+=(UL)i*mi[i];
loc[i]=1;
}
s.insert(0);s.insert(m+1);
s.insert(1);cnt[1]=n;
for (int i=1;i<=q;++i)
{
char opt=getchar();
while (opt!='C'&&opt!='W') opt=getchar();
int x,y;scanf("%d%d",&x,&y);
if (opt=='C')
{
--cnt[loc[x]];
if (hash[loc[x]]&&!mp[hash[loc[x]]])
s.erase(loc[x]);
hash[loc[x]]-=(UL)x*mi[x];
if (hash[loc[x]]&&!mp[hash[loc[x]]])
s.insert(loc[x]);
++cnt[y];
if (hash[y]&&!mp[hash[y]])
s.erase(y);
hash[y]+=(UL)x*mi[x];
if (hash[y]&&!mp[hash[y]])
s.insert(y);
loc[x]=y;
}
else
{
set<int>::iterator l,r,t,del;
ans=0;
l=s.lower_bound(x);r=s.upper_bound(y);
for (t=l;t!=r;)
{
ans+=cnt[*t];
mp[hash[*t]]=1;
del=t;++t;
s.erase(del);
}
printf("%d\n",ans);
}
}
}