Submission #1294064

#TimeUsernameProblemLanguageResultExecution timeMemory
1294064julia_08Making Friends on Joitter is Fun (JOI20_joitter2)C++20
100 / 100
499 ms68580 KiB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const int MAXN = 1e5 + 10;

int pai[MAXN];

set<int> in[MAXN], out[MAXN]; // components

set<int> vtx[MAXN]; // vertices that go into the component

set<int> comp[MAXN]; // component itself

queue<pair<int, int>> q;

ll ans;

int get_size(int a){
  return (int) (in[a].size() + out[a].size() + vtx[a].size() + comp[a].size());
}

ll get_ans(int a){

  ll sz = (ll) comp[a].size(), sz_out = (ll) vtx[a].size();
  return sz_out * sz + (sz * (sz - 1));

}

int get(int v){
  if(v == pai[v]) return v;
  return pai[v] = get(pai[v]);
}

void dsu_union(int a, int b){

  a = get(a);
  b = get(b);

  if(a == b) return;

  ans -= get_ans(a);
  ans -= get_ans(b);

  int sz_a = get_size(a), sz_b = get_size(b);

  if(sz_a > sz_b) swap(a, b);

  pai[a] = b;  

  in[a].erase(b); in[b].erase(a);
  out[a].erase(b); out[b].erase(a);

  for(auto x : comp[a]){

    comp[b].insert(x);
    if(vtx[b].count(x)) vtx[b].erase(x);

  }

  for(auto x : in[a]){

    x = get(x);

    out[x].erase(a);
    out[x].insert(b);

    if(!out[b].count(x)){

      in[b].insert(x);

    } else{
  
      out[b].erase(x);      
      q.push({x, b});

    }
  
  }

  for(auto x : vtx[a]){

    int rx = get(x);

    if(rx == b) continue;

    if(!out[b].count(rx)){
      vtx[b].insert(x);
    } else vtx[b].erase(x);

  }

  for(auto x : out[a]){

    x = get(x);

    in[x].erase(a);
    in[x].insert(b);

    if(!in[b].count(x)){
      
      out[b].insert(x);
    
    } else{

      in[b].erase(x);
      q.push({x, b});

    }

  }

  in[a].clear(); out[a].clear();
  vtx[a].clear(); comp[a].clear();

  ans += get_ans(b);

}

int main(){
  cin.tie(0)->sync_with_stdio(0);

  int n, m; cin >> n >> m;

  for(int i=1; i<=n; i++){
    pai[i] = i;
    comp[i] = {i};
  }

  int cnt = 0;

  while(m--){

    int a, b; cin >> a >> b;

    int ra = get(a), rb = get(b);

    ans -= get_ans(rb);

    if(ra != rb){

      in[rb].insert(ra);
      out[ra].insert(rb);

      vtx[rb].insert(a);

      if(in[ra].count(rb)) q.push({ra, rb});

    }

    ans += get_ans(rb);

    while(!q.empty()){

      auto [a, b] = q.front();
      q.pop();
      
      dsu_union(a, b);
    
    }

    cout << ans << "\n";

  }

  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...