99网
您的当前位置:首页2020 China Collegiate Programming Contest Weihai Site H.Message Bomb

2020 China Collegiate Programming Contest Weihai Site H.Message Bomb

来源:99网

H.Message Bomb


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

  • 可以用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;
}

因篇幅问题不能全部显示,请点此查看更多更全内容