This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |