题目大意:
有
n
n
n 个房间(一个人可以在多个房间,其实可以将这个房间类比成QQ群),
m
m
m 个人,
q
q
q 次操作,操作分为三种
1.将学生
x
x
x 加入
y
y
y 号房间
2.将学生
x
x
x 在
y
y
y 号房间中去除
3.令学生
x
x
x 在
y
y
y 号房间中发一条信息(房间中除了
x
x
x 的每个人消息数+1)
问经过
q
q
q 次操作后每个人收到了多少条消息
题目分析:
用一个
s
e
t
set
set 数组维护每个人加入的房间编号,用两个数组
s
t
u
,
r
o
o
m
stu,room
stu,room分别记录每个人每个房间收到了多少条信息
当将
x
x
x 加入
y
y
y 号房间时,我们用差分的思想将
s
t
u
[
x
]
stu[x]
stu[x] 减去
y
y
y 号房间之前发的消息数以避免之前操作对
x
x
x 的影响
当将
x
x
x 从
y
y
y 号房间去除时,同样是差分思想我们将
s
t
u
[
x
]
stu[x]
stu[x] 加上
y
y
y 号房间中的消息数即可
当让
x
x
x 在
y
y
y 号房间中发一条信息时,我们可以让
s
t
u
[
x
]
−
−
,
r
o
o
m
[
y
]
+
+
stu[x]--,room[y]++
stu[x]−−,room[y]++ 来让除了
x
x
x 以外的在
y
y
y 号房间中的人的消息数+1
最后我们统计一下每个人的
s
e
t
set
set 累加出其收到的所有信息数即可
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 2e5+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
set<int> sets[maxn]; //sets[i]表示当前i号同学加入的房间
int stu[maxn],room[maxn];
int main()
{
int n = read(),m = read(),q = read();
while(q--)
{
int opt = read(),x = read(),y = read();
if(opt == 1)
{
stu[x] -= room[y];
sets[x].insert(y);
}
else if(opt == 2)
{
stu[x] += room[y];
sets[x].erase(y);
}
else {
stu[x]--;
room[y]++;
}
}
for(int i = 1;i <= m;i++)
{
for(auto it:sets[i])
{
stu[i] += room[it];
}
printf("%d\n",stu[i]);
}
return 0;
}