Submission #1091081

#TimeUsernameProblemLanguageResultExecution timeMemory
1091081steveonalexMaking Friends on Joitter is Fun (JOI20_joitter2)C++17
100 / 100
572 ms68440 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MASK(i) (1LL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() #define block_of_code if(true) ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll gcd(ll a, ll b){return __gcd(a, b);} ll lcm(ll a, ll b){return a / gcd(a, b) * b;} ll LASTBIT(ll mask){return (mask) & (-mask);} int pop_cnt(ll mask){return __builtin_popcountll(mask);} int ctz(ull mask){return __builtin_ctzll(mask);} int logOf(ull mask){return 63 - __builtin_clzll(mask);} mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); ll rngesus(ll l, ll r){return l + (ull) rng() % (r - l + 1);} double rngesus_d(double l, double r){ double cur = rngesus(0, MASK(60) - 1); cur /= MASK(60) - 1; return l + cur * (r - l); } template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){ for(auto item: container) out << item << separator; out << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } pair<int, int> make_edge(int u, int v){ if (u <= v) return make_pair(u, v); return make_pair(v, u); } struct DSU{ int n; vector<int> parent, sz; vector<vector<int>> ver; vector<set<int>> S1, S2, drake; set<pair<int, int>> pending_merge; ll ans; DSU(int _n){ n = _n; parent.resize(n+1); sz.resize(n+1, 1); S1.resize(n+1); S2.resize(n+1); drake.resize(n+1); ver.resize(n+1); for(int i = 1; i<=n; ++i) { parent[i] = i; ver[i].push_back(i); } ans = 0; } int find_set(int u){return (u == parent[u]) ? u : (parent[u] = find_set(parent[u]));} bool same_set(int u, int v){return find_set(u) == find_set(v);} bool join_set(int u, int v){ u = find_set(u), v = find_set(v); if (u == v) return false; ans += 2LL * sz[u] * sz[v]; S1[u].erase(v); S2[u].erase(v); S1[v].erase(u); S2[v].erase(u); ans -= 1LL * sz[v] * drake[v].size() + 1LL * sz[u] * drake[u].size(); if (sz[u] < sz[v]) swap(u, v); parent[v] = u; sz[u] += sz[v]; vector<pair<int, int>> pending; for(int i: S1[v]) { S2[i].erase(v); S2[i].insert(u); S1[u].insert(i); if (S2[u].find(i) != S2[u].end()) pending_merge.insert({u, i}); } for(int i: S2[v]){ S1[i].erase(v); S1[i].insert(u); S2[u].insert(i); if (S1[u].find(i) != S1[u].end()) pending_merge.insert({u, i}); } for(int i: ver[v]) drake[u].erase(i); ans += 1LL * sz[u] * drake[u].size(); for(int i: drake[v]) if (!same_set(u, i)) add_drake(u, i); for(int i: ver[v]) ver[u].push_back(i); return true; } void add_drake(int u, int v){ if (drake[u].insert(v).second) { ans += get_size(u); } } int get_size(int u){return sz[find_set(u)];} ll get_ans(){return ans;} void add_edge(int u, int v){ int _u = u; u = find_set(u), v = find_set(v); S1[u].insert(v); S2[v].insert(u); add_drake(v, _u); if (S2[u].find(v) != S2[u].end()) pending_merge.insert({u, v}); while(pending_merge.size()){ int x, y; tie(x, y) = *pending_merge.begin(); pending_merge.erase(pending_merge.begin()); join_set(x, y); } } }; int main(void){ ios::sync_with_stdio(0);cin.tie(0); cout.tie(0); clock_t start = clock(); // freopen("input.inp", "r", stdin); int n, m; cin >> n >> m; DSU mst(n); for(int i = 0; i<m; ++i){ int u, v; cin >> u >> v; if (!mst.same_set(u, v)) mst.add_edge(u, v); ll ans = mst.get_ans(); cout << ans << "\n"; } cerr << "Time elapsed: " << clock() - start << " ms\n"; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...