2020CCPC威海 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 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) (1n100000,1m200000,1s1000000), 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},1xm,1yn) 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sky123_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值