题目链接
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 n n groups and m m m students. Every group contains a subset of the m m 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 n, m, s n,m,s ( 1 ≤ n ≤ 100 000 , 1 ≤ m ≤ 200 000 , 1 ≤ s ≤ 1 000 000 ) (1 \leq n \leq 100\,000, 1 \leq m \leq 200\,000, 1 \leq s \leq 1\,000\,000) (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 s s lines give the events in the log in chronological order. Each of them contains three integers t , x , y t, x, y t,x,y ( t ∈ { 1 , 2 , 3 } , 1 ≤ x ≤ m , 1 ≤ y ≤ n ) (t \in \{1, 2, 3\}, 1 \leq x \leq m, 1 \leq y \leq n) (t∈{1,2,3},1≤x≤m,1≤y≤n) specifying an event, which may fall into one of the following three categories:
- If t = 1 t = 1 t=1, it means that the x x x-th student joined in the y y y-th group. It is guaranteed that the student was not in the group before.
- If t = 2 t = 2 t=2, it means that the x x x-th student quitted the y y y-th group. It is guaranteed that the student was currently in the group.
- If t = 3 t = 3 t=3, it means that the x x x-th student sent a message in the y y y-th group. It is guaranteed that the student was in the group now.
Initially, all groups were empty.
Output
Output m m m lines. The i i i-th line contains an integer, denoting the total number of messages the i i i-th student received.
Examples
input
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
2
0
1
input
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
2
0
1
1
0
现场做法:
对于每个群按照时间轴建树状数组,然后对于每个人在这个群里发的消息,在对应时间加
1
1
1 ,对于每个人在群里的时间,在树状数组上区间求和累加到对应人。
这道题属实写麻烦了
#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define pb push_back
#define fi first
#define se second
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 1e6 + 10, M = 1e5 + 10;
struct BIT {
int t[N], n;
inline int ask(int k) {
int ans = 0;
for (int i = k; i; i -= lowbit(i))ans += t[i];
return ans;
}
inline void add(int x, int v) {
for (int i = x; i <= n; i += lowbit(i))t[i] += v;
}
} B;
vector<pair<int, pair<int, int>>> st[M];
vector<pair<int, int> > me[M];
int n, m, s;
int ans[M << 1];
vector<int> l[N << 1], r[N << 1], tmp;
inline void calc(int x) {
for (auto it:me[x])B.add(it.fi, 1), ans[it.se]--;
for (auto it:st[x]) {
if (it.se.se == 1) {
if (l[it.se.fi].empty())tmp.pb(it.se.fi);
l[it.se.fi].pb(it.fi);
} else r[it.se.fi].pb(it.fi);
}
for (auto i:tmp) {
if (r[i].size() < l[i].size())r[i].pb(s);
for (int j = 0; j <= l[i].size() - 1; ++j)
ans[i] += B.ask(r[i][j]) - B.ask(l[i][j]);
l[i].clear(), r[i].clear();
}
tmp.clear();
for (auto it:me[x])B.add(it.fi, -1);
}
int main() {
n = qr(), m = qr(), s = qr();
for (int i = 1; i <= s; ++i) {
int t = qr(), x = qr(), y = qr();
switch (t) {
case 1:
st[y].pb({i - 1, {x, 1}});
break;
case 2:
st[y].pb({i, {x, -1}});
break;
default:
me[y].pb({i, x});
}
}
B.n = s;
for (int i = 1; i <= n; ++i)calc(i);
for (int i = 1; i <= m; ++i)printf("%d\n", ans[i]);
return 0;
}
正解:
对于每个群记录当前群内发的信息,然后把事件遍历一遍差分即可。
#include<bits/stdc++.h>
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 1e5 + 10, M = 2e5 + 10;
int cnt[N], ans[M];
set<int> g[N];
int n, m, s;
int main() {
n = qr(), m = qr(), s = qr();
for (int i = 1; i <= s; ++i) {
int t = qr(), x = qr(), y = qr();
switch (t) {
case 1:
g[y].insert(x), ans[x] -= cnt[y];
break;
case 2:
g[y].erase(x), ans[x] += cnt[y];
break;
default:
cnt[y]++, ans[x]--;
}
}
for (int i = 1; i <= n; ++i)
for (auto it:g[i])ans[it] += cnt[i];
for (int i = 1; i <= m; ++i)
printf("%d\n", ans[i]);
return 0;
}