1. 程式人生 > 其它 >P3998 [SHOI2013]發微博(差分+set維護)

P3998 [SHOI2013]發微博(差分+set維護)

題目傳送門

題意

n個使用者,m次操作,操作有三種,如下:

  • ! x 表示使用者 x 發了一條微博;

  • + x y 表示使用者 x 和使用者 y 成為了好友

  • − x y 表示使用者 x 和使用者 y 解除了好友關係

當一個使用者發微博的時候,所有他的好友(直接關係)都會看到他的訊息。
假設最開始所有人之間都不是好友關係,記錄也都是合法的(即 + x y 時 x 和 y 一定不是好友,而 − x y 時 x 和 y 一定是好友)。
問這 m 條記錄發生之後,每個使用者分別看到了多少條訊息。

輸入格式

第 1 行兩個整數 n, m。
接下來 m 行,按時間順序讀入 m 條記錄,每條記錄的格式如題目所述,用空格隔開。

輸出格式

輸出一行 n 個用空格隔開的數(行末無空格),第 i 個數表示使用者 i 最後看到了幾條訊息。

資料範圍

對於 100% 的資料,n≤200000, m≤500000

樣例

input

2 8
! 1
! 2
+ 1 2
! 1
! 2
- 1 2
! 1
! 2

output

1 1

思路

如果一個人發微博了,那麼對於他的所有好友,他的所有好友看到的微博數量就會加1。
考慮y看到的x發的微博數量,其實就是他們成為好友到解除好友之間的x發的微博數量,也就是ans[y]=ans[y]+cnt[x]-(cnt[x])',他們刪除好友時x發的微博數量減去他們剛成為好友時x發的微博數量。
於是我們用cnt[x]記錄x到當前操作的時候已經發了多少微博,並且對於每個點建立一個set,記錄這個點有哪些好友,每次加好友的時候先減去當前該好友發的微博數量,然後在刪好友的時候再加上當前好友已經發的微博數量。
當所有操作結束的時候,需要手動將所有的好友都刪掉,更新微博數量。

code

#include <bits/stdc++.h>
using  namespace  std;

typedef long long ll;
typedef unsigned long long ull;
//#pragma GCC optimize(3)
#define pb push_back
#define is insert
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define show(x) cerr<<#x<<" : "<<x<<endl;
//mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
//ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}

const ll INF=0x3f3f3f3f3f3f3f3f;//2147483647;
const int N=2e5+50,M=1e5+50;
const ll mod=998244353;

int n,m;
int cnt[N],ans[N];
set<int>s[N];
void solve() {
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        char op;cin>>op;
        if(op=='!'){
            int tmp;cin>>tmp;
            cnt[tmp]++;
        }
        else if(op=='+'){
            int x,y;cin>>x>>y;
            s[x].is(y);s[y].is(x);
            ans[x]-=cnt[y];
            ans[y]-=cnt[x];
        }
        else {
            int x,y;cin>>x>>y;
            s[x].erase(y);s[y].erase(x);
            ans[x]+=cnt[y];ans[y]+=cnt[x];
        }
    }
    for(int i=1;i<=n;i++){
        for(auto j:s[i]){
            ans[i]+=cnt[j];
        }
    }
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<" ";
    }
}

signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int __=1;//cin>>__;
    while(__--){
        solve();
    }
    return 0;
}