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;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-05-12 Codeforces Round #639 (Div. 2) C. Hilbert's Hotel(数学)