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...