2020ccpc 威海 Message Bomb(差分)

在这里插入图片描述
题目大意:
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值