2020 China Collegiate Programming Contest Weihai Site H.Message Bomb

H.Message Bomb

题目链接-H.Message Bomb
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题目大意
输入 s s s行数据,
如果 t = 1 t=1 t=1,则表示第x个学生加入了第 y y y个组。可以肯定的是,这个学生以前不在这个小组里。
如果 t = 2 t=2 t=2,则表示第x个学生退出了第 y y y个组。可以肯定的是,这名学生目前就在这个组里。
如果 t = 3 t=3 t=3,则表示第 x x x个学生在第 y y y个组中发送了一条消息,可以肯定的是,那个学生现在就在小组里
消息将广播给当前在同一组中的所有其他成员,求最后每个人各自收到的消息总数

解题思路
差 分 思 想 差分思想

  • 可以用set统计每个学生加入的组,数组 b b b统计每个组一共中发消息的条数,数组 a a a作为差分数组统计每个人各自收到的消息数
  • 当进组时我们就用s[x].insert(y)统计,同时a[x]-=b[y],即先减去进组之前的消息数,退组时就用s[x].erase(y)将该组删除,然后只需a[x]+=b[y],加上现在该组消息的总数,根据差分思想,即相当于加上从进组到退组这段时间 x x x y y y组收到的消息总数
  • x x x y y y组发邮件时,因为消息将广播给当前在同一组中的所有其他成员,所以只需a[x]--,b[y]++(a[x]--是为了避免后续统计消息数时加上自己发的消息)
  • 最后重新按照第二条遍历一遍每人所加入的组,加上相应的邮件数输出即可
  • 具体操作见代码

附上代码

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x &(-x))
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const double PI=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=2e5+10;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
inline void read(int &x){
    char t=getchar();
    while(!isdigit(t)) t=getchar();
    for(x=t^48,t=getchar();isdigit(t);t=getchar()) x=x*10+(t^48);
}
set<int> s[N];
int a[N],b[N];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);

	int n,m,s1;
	cin>>n>>m>>s1;
	while(s1--){
		int t,x,y;
		cin>>t>>x>>y;
		if(t==1){
			a[x]-=b[y];
			s[x].insert(y);
		}
		else if(t==2){
			a[x]+=b[y];
			s[x].erase(y);
		}
		else{
			b[y]++;
			a[x]--;
		}
	}
	set<int>::iterator it;
	for(int i=1;i<=m;i++){
		for(it=s[i].begin();it!=s[i].end();it++)
			a[i]+=b[*it];
		cout<<a[i]<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值