Submission #1265403

#TimeUsernameProblemLanguageResultExecution timeMemory
1265403rajarshi_basuMaking Friends on Joitter is Fun (JOI20_joitter2)C++20
0 / 100
0 ms320 KiB
#include <bits/stdc++.h> using namespace std; struct DSU { int n; vector<int> p, sz; DSU(int n=0): n(n), p(n+1), sz(n+1,1) { iota(p.begin(), p.end(), 0); } int find(int x){ return p[x]==x?x:p[x]=find(p[x]); } // caller decides which root becomes parent void link_root(int child, int parent){ p[child]=parent; sz[parent]+=sz[child]; } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N,M; if(!(cin>>N>>M)) return 0; DSU dsu(N); // out[u] = users v that u follows (to detect mutual quickly) vector<unordered_set<int>> out(N+1); out.shrink_to_fit(); // For each component root r: // sources[r] = set of distinct users x that have at least one edge x->(any member of r) // inside[r] = count of x in sources[r] that are also members of r vector<unordered_set<int>> sources(N+1); vector<long long> inside(N+1, 0); long long ans = 0; auto add_source = [&](int comp, int x){ // Insert x into sources[comp]; update ans and inside if first time if(sources[comp].insert(x).second){ ans += dsu.sz[comp]; if(dsu.find(x)==comp){ inside[comp] += 1; ans -= 1; // exclude self-follow } } }; auto unite = [&](int a, int b){ int ra = dsu.find(a), rb = dsu.find(b); if(ra==rb) return; // Parent by component size if(dsu.sz[ra] < dsu.sz[rb]) swap(ra, rb); // ra will be parent root // Ensure we merge smaller sources-set into larger (small-to-large) if(sources[ra].size() < sources[rb].size()){ swap(sources[ra], sources[rb]); swap(inside[ra], inside[rb]); } // Remove old contributions long long term_ra = 1LL * dsu.sz[ra] * (long long)sources[ra].size() - inside[ra]; long long term_rb = 1LL * dsu.sz[rb] * (long long)sources[rb].size() - inside[rb]; ans -= term_ra + term_rb; // Prepare new values long long extra_inside = 0; size_t before_sz = sources[ra].size(); // Merge sources[rb] into sources[ra] for(const int s : sources[rb]){ auto ins = sources[ra].insert(s); if(ins.second){ int rs = dsu.find(s); // membership BEFORE union if(rs==ra || rs==rb) extra_inside += 1; } } sources[rb].clear(); inside[ra] = inside[ra] + inside[rb] + extra_inside; long long new_comp_size = dsu.sz[ra] + dsu.sz[rb]; long long new_sources_cnt = (long long)sources[ra].size(); // Add new contribution ans += new_comp_size * new_sources_cnt - inside[ra]; // Union components in DSU dsu.link_root(rb, ra); }; for(int i=1;i<=M;i++){ int A,B; cin>>A>>B; // Add A->B if new (problem guarantees no duplicates, but keep safe) if(out[A].insert(B).second){ int cb = dsu.find(B); add_source(cb, A); } // If mutual found, merge components of A and B if(out[B].count(A)) unite(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...