Submission #1000233

#TimeUsernameProblemLanguageResultExecution timeMemory
1000233UnforgettableplMaking Friends on Joitter is Fun (JOI20_joitter2)C++17
100 / 100
355 ms62544 KiB
#include <bits/stdc++.h> using namespace std; #define int long long struct UFDS{ vector<int> p,siz; vector<set<pair<int,int>>> incoming,outgoing; UFDS(int n):p(n+1),siz(n+1,1),incoming(n+1),outgoing(n+1){iota(p.begin(),p.end(),0);} int findRoot(int x){ return p[x]==x ? x : p[x]=findRoot(p[x]); } int merge(int x,int y){ if(findRoot(x)==findRoot(y))return 0; x = findRoot(x); y = findRoot(y); int ans = 0; int root_x = x; while(true){ auto iter = incoming[root_x].lower_bound({y,0ll}); if(iter==incoming[root_x].end() or iter->first!=y)break; outgoing[y].erase({root_x,iter->second}); incoming[root_x].erase(iter); ans-=siz[root_x]; } while(true){ auto iter = incoming[y].lower_bound({root_x,0ll}); if(iter==incoming[y].end() or iter->first!=root_x)break; outgoing[root_x].erase({y,iter->second}); incoming[y].erase(iter); ans-=siz[y]; } ans-=siz[root_x]*incoming[root_x].size(); ans-=siz[y]*incoming[y].size(); ans-=siz[root_x]*(siz[root_x]-1ll); ans-=siz[y]*(siz[y]-1ll); if(incoming[root_x].size()+outgoing[root_x].size()<incoming[y].size()+outgoing[y].size())swap(root_x,y); p[y] = root_x; siz[root_x]+=siz[y]; vector<int> qu; for(auto[a,b]:incoming[y]){ incoming[root_x].insert({a,b}); auto iter = outgoing[root_x].lower_bound({a,0}); if(iter!=outgoing[root_x].end() and iter->first==a)qu.emplace_back(a); outgoing[a].erase({y,b}); outgoing[a].insert({root_x,b}); } for(auto[a,b]:outgoing[y]){ outgoing[root_x].insert({a,b}); auto iter = incoming[root_x].lower_bound({a,0}); if(iter!=incoming[root_x].end() and iter->first==a)qu.emplace_back(a); incoming[a].erase({y,b}); incoming[a].insert({root_x,b}); } ans+=siz[root_x]*incoming[root_x].size(); ans+=siz[root_x]*(siz[root_x]-1); for(int&i:qu)ans+=merge(root_x,i); return ans; } int unite(int x,int y){ int root_x = findRoot(x); y = findRoot(y); if(y==root_x)return 0; if(outgoing[root_x].count({y,x}))return 0; auto iter = incoming[root_x].lower_bound({y,0ll}); if(iter!=incoming[root_x].end() and iter->first==y){ return merge(root_x,y); } outgoing[root_x].insert({y,x}); incoming[y].insert({root_x,x}); return siz[y]; } }; UFDS dsu(100000); int32_t main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); int n,m; cin >> n >> m; int ans = 0; for(int i=1;i<=m;i++){ int a,b;cin>>a>>b; ans+=dsu.unite(a,b); cout << ans << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...