제출 #216570

#제출 시각아이디문제언어결과실행 시간메모리
216570combi1k1조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2)C++14
100 / 100
816 ms55928 KiB
#include<bits/stdc++.h>

using namespace std;

#define ll  long long
#define ld  double

#define sz(x)   (int)x.size()
#define all(x)  x.begin(),x.end()

#define pb  emplace_back
#define X   first
#define Y   second

const int   N   = 1e5 + 5;

typedef pair<int,int>   ii;

int p[N];
int s[N];

ll  ans = 0;

queue<ii>   pending;

int lead(int x) {
    return p[x] == x ? x : p[x] = lead(p[x]);
}

struct Edge {
    int pa, a;
    int pb;

    Edge(int _a = 0,int _b = 0) : pa(lead(_a)), a(_a), pb(lead(_b)) {}
};
bool operator < (const Edge&x,const Edge&y) {
    auto tmp1 = make_tuple(x.pa,x.pb,x.a);
    auto tmp2 = make_tuple(y.pa,y.pb,y.a);

    return  tmp1 < tmp2;
}
set<Edge> fr[N];
set<Edge> to[N];
unordered_map<int,int>  cnt[N];

void addEdge(int x,int y)   {   //an egde directed from x to y
    int a = lead(x);
    int b = lead(y);

    if (a == b) return;

    Edge E(y,x);    E.a = 0;
    auto it = fr[b].lower_bound(E);

    if (it == fr[b].end() || (*it).pb != a) {
        E = Edge(x,y);

        if(!fr[a].count(E)) {
            fr[a].insert(E);
            to[b].insert(E);    ans += s[b];
        }
        return;
    }
    pending.push(ii(a,b));
}

int main()  {
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int n;  cin >> n;
    int m;  cin >> m;

    iota(p + 1,p + 1 + n,1);
    fill(s + 1,s + 1 + n,1);

    for(int i = 0 ; i < m ; ++i)    {
        int x;  cin >> x;
        int y;  cin >> y;   addEdge(x,y);

        while (pending.size())  {
            int x = lead(pending.front().X);
            int y = lead(pending.front().Y);

            pending.pop();

            if (x == y) continue;

            Edge E(x,y);    E.a = 0;
            Edge F(y,x);    F.a = 0;

            vector<Edge> remA;
            vector<Edge> remB;

            for(auto it = fr[x].lower_bound(E) ; it != fr[x].end() && (*it).pb == y ; remA.pb(*it++));
            for(auto it = fr[y].lower_bound(F) ; it != fr[y].end() && (*it).pb == x ; remB.pb(*it++));

            for(Edge E : remA)  fr[x].erase(E), to[y].erase(E);
            for(Edge E : remB)  fr[y].erase(E), to[x].erase(E);

            ans -= 1ll * sz(remA) * s[y];
            ans -= 1ll * sz(remB) * s[x];

            if (sz(fr[x]) + sz(to[x]) < sz(fr[y]) + sz(to[y]))
                swap(x,y);

            ans += 2ll * s[x] * s[y];

            ans += 1ll * s[y] * sz(to[x]);
            ans -= 1ll * s[y] * sz(to[y]);

            p[y] = x;
            s[x] += s[y];

            for(Edge E : to[y]) fr[E.pa].erase(E),  addEdge(E.a,x);
            for(Edge E : fr[y]) to[E.pb].erase(E),  addEdge(E.a,E.pb),
                ans -= s[E.pb];

            fr[y].clear();
            to[y].clear();
        }
//        ll  ans = 0;
//
//        for(int j = 1 ; j <= n ; ++j)
//            if (j == p[j])
//                ans += 1ll * s[j] * (s[j] - 1),
//                ans += 1ll * s[j] * sz(to[j]);

        cout << ans << "\n";
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...