题目大意:有一些人一开始都在一号房间。有一些指令使他们区别的房间。每次选定一段区间作试验,如果有的房间的组合已经做过试验,那么就不计入最后的试验点数,否则计入试验点数为试验的人数。问最后会获得多少试验点数。
思路:对于每一个人随即一个long long,一个集合所代表的数字就是这些long long的异或和。然后用set来暴力判重。
CODE:
#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std;
int points,cnt,asks;
unsigned long long src[MAX];
char c[10];
int size[MAX],_in[MAX];
set<unsigned long long> used;
set<int> status;
unsigned long long now[MAX];
int main()
{
srand(19970806);
cin >> points >> cnt >> asks;
for(int i = 1; i <= points; ++i) {
src[i] = (unsigned long long)rand() * rand() * rand();
now[1] ^= src[i];
_in[i] = 1;
}
size[1] = points;
status.insert(1);
for(int x,y,i = 1; i <= asks; ++i) {
scanf("%s%d%d",c,&x,&y);
if(c[0] == 'C') {
size[_in[x]]--;
size[y]++;
if(status.find(_in[x]) != status.end())
status.erase(_in[x]);
if(status.find(y) != status.end())
status.erase(y);
now[_in[x]] ^= src[x];
now[y] ^= src[x];
if(used.find(now[_in[x]]) == used.end())
status.insert(_in[x]);
if(used.find(now[y]) == used.end())
status.insert(y);
_in[x] = y;
}
else {
static set<int>::iterator it;
int ans = 0;
it = status.lower_bound(x);
for(;it != status.end() && *it <= y;) {
ans += size[*it];
used.insert(now[*it]);
status.erase(it);
it = status.lower_bound(x);
}
printf("%d\n",ans);
}
}
return 0;
}