Loading

2020 China Collegiate Programming Contest, Weihai Site H. Message Bomb(差分/思维/好题)

While we enjoy chatting with friends on the internet, it is always annoying that we are overwhelmed by lots of messages in various chat groups. A great majority of these messages are actually not interesting to us, but we may miss some important notices if we silence these groups. How many messages do we receive from all online chat groups? Nobody has ever seriously gone into this question.

As an assistant researcher in the school of informatics, you are required to investigate the number of online messages we receive every day. We have already sampled 𝑛n groups and 𝑚m students. Every group contains a subset of the 𝑚m students, which is possibly empty. Also, the members of the groups are constantly evolving; old members may quit, and new members may join in a chat group. Members can send messages in the group; the message is broadcast to all other members currently in the same group.

Now we have collected the log of these chat groups. The log is a sequence of events, which may be a student joining in a group, quitting a group, or sending a message in a group. Your task is to compute the total number of messages received by every student.

Input

The first line of the input contains three integers 𝑛,𝑚,𝑠n,m,s (1≤𝑛≤100000,1≤𝑚≤200000,1≤𝑠≤1000000)(1≤n≤100000,1≤m≤200000,1≤s≤1000000), denoting the number of groups, the number of students and the number of events in the log.

The next 𝑠s lines give the events in the log in chronological order. Each of them contains three integers 𝑡,𝑥,𝑦t,x,y (𝑡∈{1,2,3},1≤𝑥≤𝑚,1≤𝑦≤𝑛)(t∈{1,2,3},1≤x≤m,1≤y≤n) specifying an event, which may fall into one of the following three categories:

  • If 𝑡=1t=1, it means that the 𝑥x-th student joined in the 𝑦y-th group. It is guaranteed that the student was not in the group before.
  • If 𝑡=2t=2, it means that the 𝑥x-th student quitted the 𝑦y-th group. It is guaranteed that the student was currently in the group.
  • If 𝑡=3t=3, it means that the 𝑥x-th student sent a message in the 𝑦y-th group. It is guaranteed that the student was in the group now.

Initially, all groups were empty.

Output

Output 𝑚m lines. The 𝑖i-th line contains an integer, denoting the total number of messages the 𝑖i-th student received.

Examples

input

Copy

3 3 10
1 3 2
1 3 1
1 1 2
1 2 1
3 1 2
2 3 1
3 3 2
3 2 1
3 3 2
3 2 1

output

Copy

2
0
1

input

Copy

2 5 10
1 1 2
3 1 2
2 1 2
1 3 2
1 1 2
3 1 2
3 3 2
1 4 2
3 3 2
1 5 1

output

Copy

2
0
1
1
0

没有想到差分(或者说前缀和?)还能这么用..属实没想到

开两个数组ans和cnt,ans[i]表示i这个人最终接收到的信息数,cnt[i]表示i这个组中发出的信息数,再开一个set数组记录一个人所属的组(可能有多个)。

当一个人加入一个组又退出后对其ans的影响为退出时组中发出的信息数-加入前组中发出的信息数-他在这个组中发出的信息数,可以用差分的思想实现。注意最后统计答案时好多人可能还没从组里退出来,这时候需要我们手动把它们从组里退出来计算贡献,set数组就起作用了(当然也可以不用这么暴力)。

#include <bits/stdc++.h>
using namespace std;
int n, m, s;
int ans[200005], cnt[200005];
set<int> belong[200005];
int main() {
	cin >> n >> m >> s;
	memset(ans, 0, sizeof(ans));
	memset(cnt, 0, sizeof(cnt));
	
	for(int i = 1; i <= s; i++) {
		
		int t, x, y;
		scanf("%d%d%d", &t, &x, &y);
		if(t == 1) {
			ans[x] -= cnt[y];
			belong[x].insert(y);
		} else if(t == 2) {
			ans[x] += cnt[y];
			set<int>::iterator it = belong[x].find(y);
			belong[x].erase(it);
		} else {
			cnt[y]++;
			ans[x]--;//提前减去他自己发的(这一部分包含在了cnt里 必须要减去)
		}    
	}
	for(int x = 1; x <= m; x++) {
		if(belong[x].size() == 0) {//完全退出来了,ans直接就是答案
			cout << ans[x] << endl;
		}
		else {
			set<int>::iterator it;
			for(it = belong[x].begin(); it != belong[x].end(); it++) {
				ans[x] += cnt[*it];//手动退组
			}
			cout << ans[x] << endl;
		}
	}
}
posted @ 2021-05-12 00:59  脂环  阅读(129)  评论(0编辑  收藏  举报