Submission #212010

#TimeUsernameProblemLanguageResultExecution timeMemory
212010EntityITMaking Friends on Joitter is Fun (JOI20_joitter2)C++14
100 / 100
1241 ms87932 KiB
#include<bits/stdc++.h>

using namespace std;

#define all(x) (x).begin(), (x).end()
#define sz(x) ( (int)(x).size() )
using LL = long long;

mt19937 rng( (uint32_t)chrono::steady_clock::now().time_since_epoch().count() );

struct Dsu {
  vector<int> pSet, nEle;
  LL nEdge;
  vector<map<int, set<int> > > edge;
  vector<set<int> > in, out;
  queue<pair<int, int> > q;
  Dsu(int nSet) {
    pSet.assign(nSet, 0); iota(all(pSet), 0);
    nEle.assign(nSet, 1);
    nEdge = 0;
    edge.assign(nSet, {});
    in.assign(nSet, {});
    out.assign(nSet, {});
  }

  int findSet(int i) { return i ^ pSet[i] ? pSet[i] = findSet(pSet[i]) : i; }
  void unite(int i, int j) {
    i = findSet(i); j = findSet(j);

    if (i == j) return ;

    if (nEle[i] > nEle[j]) swap(i, j);

    nEdge -= (LL)sz(edge[i][j]) * nEle[j]
             + (LL)sz(edge[j][i]) * nEle[i];
    for (const auto &k : edge[i][j]) {
      out[k].erase(j);
      in[j].erase(k);
    }
    edge[i].erase(j);
    for (const auto &k : edge[j][i]) {
      out[k].erase(i);
      in[i].erase(k);
    }
    edge[j].erase(i);
    nEdge += (LL)nEle[i] * nEle[j] * 2;

    nEdge -= (LL)sz(in[i]) * nEle[i] + (LL)sz(in[j]) * nEle[j];
    for (const auto &k : in[i]) {
      in[j].emplace(k);
      if (edge[j].find(findSet(k) ) != edge[j].end() ) q.emplace(j, k);
      out[k].erase(i); edge[findSet(k)][i].erase(k);
      out[k].emplace(j); edge[findSet(k)][j].emplace(k);
    }
    for (const auto &k : edge[i]) {
      for (const auto &t : k.second) {
        edge[j][k.first].emplace(t);
        if (edge[k.first].find(j) != edge[k.first].end() ) q.emplace(k.first, j);
      }
    }
    nEdge += (LL)sz(in[j]) * (nEle[i] + nEle[j]);

    pSet[i] = j;
    nEle[j] += nEle[i];
  }
  void doQ() {
    while (sz(q) ) {
      unite(q.front().first, q.front().second);
      q.pop();
    }
  }
};

int main() {
  ios_base::sync_with_stdio(0); cin.tie(0);

  #ifdef FourLeafClover
  freopen("input", "r", stdin);
  #endif // FourLeafCLover

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

  Dsu dsu(n);
  while (m--) {
    int u, v; cin >> u >> v; --u; --v;
    int i = dsu.findSet(u), j = dsu.findSet(v);

    if (i ^ j && dsu.out[u].find(j) == dsu.out[u].end() ) {
      dsu.out[u].emplace(j); dsu.in[j].emplace(u);
      dsu.edge[i][j].emplace(u);
      dsu.nEdge += dsu.nEle[j];
      if (dsu.edge[j].find(i) != dsu.edge[j].end() ) {
        dsu.q.emplace(i, j);
        dsu.doQ();
      }
    }

//    for (int i = 0; i < n; ++i) {
//      cerr << i + 1 << " in " << dsu.findSet(i) + 1 << '\n';
//      if (i == dsu.findSet(i) ) {
//        for (const auto &j : dsu.in[i]) cerr << j + 1 << ' ';
//        cerr << '\n';
//        for (const auto &j : dsu.out[i]) cerr << j + 1 << ' ';
//        cerr << '\n';
//      }
//    }
//    cerr << "end\n";

    cout << dsu.nEdge << '\n';
  }

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