1. 程式人生 > 其它 >2020 ICPC 威海 H. Message Bomb(差分)

2020 ICPC 威海 H. Message Bomb(差分)

題目連結
題意:
三種操作:
\(t\) \(a\) \(b\)
\((1)\)\(t=1\)時,\(a\)加入團體\(b\)
\((2)\)\(t=2\)時,\(a\)離開團體\(b\)
\((3)\)\(t=3\)時,\(a\)在團體\(b\)傳送一條訊息,團隊中除自己外的人都能接收到。
求每個人接收到的訊息條數。

思路:
\(set\)+差分。
\(set[i]\)儲存團體\(i\)中的人員。
\(sum[i]\)表示當前團體\(i\)接收到的訊息數,若\(k\)在時刻\(t_1\)加入團體\(i\),在\(t_2\)時離開團體\(i\)(中途\(k\)沒有發訊息),則接收到的訊息數\(=sum[i](t2時刻)-sum[i](t1時刻)\)


最後遍歷所有的\(set\)集合,更新結束時還沒有離開團體的人員接收到的訊息數。

code:

#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;

set<int> st[maxn];
int n, m, s;
int ans[maxn], sum[maxn];

int main(){
    scanf("%d%d%d", &n, &m, &s);
    for(int i = 1; i <= s; i ++){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        if(a == 1){
            ans[b] -= sum[c];
            st[c].insert(b);
        }
        else if(a == 2){
            ans[b] += sum[c];
            st[c].erase(b);
        }
        else{
            ans[b] --;
            sum[c] ++;
        }
    }
    for(int i = 1; i <= n; i ++){
        for(int k : st[i])ans[k] += sum[i];
    }
    for(int i = 1; i <= m; i ++)printf("%d\n", ans[i]);
    return 0;
}