제출 #1182662

#제출 시각아이디문제언어결과실행 시간메모리
1182662vako_pMaking Friends on Joitter is Fun (JOI20_joitter2)C++20
0 / 100
0 ms320 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ff first
#define sd second
#define debug(x) cerr << #x << " ---> " << x << endl;
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")

const int mxN = 1e6 + 5;
ll n,m;

struct ds{
	vector<ll> node,sz,par,node1;
	vector<set<pair<ll,ll>>> in,out;
	ll ans = 0;
	
	void init(){
		par.resize(n + 5);
		sz.assign(n + 5, 1LL);
		node.resize(n + 5);
		node1.resize(n + 5);
		in.resize(n + 5);
		out.resize(n + 5);
		for(int i = 0; i < n + 5; i++) par[i] = node[i] = node1[i] = i;
	}
	
	ll find(ll at){
		if(at == par[at]) return at;
		par[at] = find(par[at]);
		return par[at];
	}
	
	void merge(ll p1, ll p2){
		pair<ll,ll> a = {find(p1), node[find(p1)]}, b = {find(p2), node[find(p2)]};
		if(a == b) return;
		if(in[a.ff].size() + out[a.sd].size() < in[b.ff].size() + out[b.sd].size()) swap(a, b);
//		cout << a.ff << ' ' << b.sd << "--------> " << (*in[a.ff].begin()).ff << '\n';
		for(auto it = in[a.ff].lower_bound({b.sd, 0}); it != in[a.ff].end() and (*it).ff == b.sd; it = in[a.ff].lower_bound({b.sd, 0})){
			ans -= sz[b.ff];
			in[a.ff].erase(it);
		}
		for(auto it = in[b.ff].lower_bound({a.sd, 0}); it != in[b.ff].end() and (*it).ff == a.sd; it = in[b.ff].lower_bound({a.sd, 0})){
			ans -= sz[a.ff];
			in[b.ff].erase(it);
		}
		ans += sz[a.ff] * sz[b.ff] * 2;
		par[b.ff] = a.ff;
		ll sz1 = sz[a.ff],sz2 = sz[b.ff];
		sz[a.ff] += sz[b.ff];
		vector<ll> v;
//		cout << a.ff << ' ' << b.ff << ' ' << in[a.ff].size() << '\n';
		for(auto it : in[b.ff]){
			in[a.ff].insert(it);
			out[it.ff].erase({b.ff, it.sd});
			out[it.ff].insert({a.ff, it.sd});
			ll at = node1[it.ff];
//			debug(it.ff);
//			debug(at);
			auto it1 = in[at].lower_bound({a.ff, 0LL});
			if(it1 != in[at].end() and (*it1).ff == a.ff) v.pb(at);
		}
		in[b.ff].clear();
		
//		if(out[a.sd].size() < out[b.sd].size()){
//			node[a.ff] = b.sd;
//			node1[b.sd] = a.ff;
//			swap(sz1, sz2);
//			swap(a, b);
//		}
		for(auto it = out[a.sd].lower_bound({b.ff, 0}); it != out[a.sd].end() and (*it).ff == b.ff; it = out[a.sd].lower_bound({b.ff, 0})){
			out[a.sd].erase(it);
		}
		for(auto it = out[b.sd].lower_bound({a.ff, 0}); it != out[b.sd].end() and (*it).ff == a.ff; it = out[b.sd].lower_bound({a.ff, 0})){
			out[b.sd].erase(it);
		}
		ans += out[a.sd].size() * sz2 + out[b.sd].size() * sz1;
		for(auto it : out[b.sd]){
			out[a.sd].insert(it);
			in[it.ff].erase({b.sd, it.sd});
			in[it.ff].insert({a.sd, it.sd});
			ll at = node[it.ff];
			auto it1 = in[a.ff].lower_bound({at, 0LL});
			if(it1 != in[a.ff].end() and (*it1).ff == at) v.pb(it.ff);
		}
		out[b.sd].clear();
		ll p = find(a.ff);
//		debug(v.size());
		for(auto it : v) merge(it, p);
	}
	
	void sett(ll a, ll b){
		ll p = find(a),p1 = find(b);
//		cout << a << ' ' << b << "----> " << node[p1] << '\n';
		if(p == p1 or out[node[p1]].find({p, a}) != out[node[p1]].end()) return;
		ans += sz[p1];
		in[p].insert({node[p1], a});
		out[node[p1]].insert({p, a});
		auto it = in[p1].lower_bound({p, 0});
		if(it != in[p1].end() and (*it).ff == p) merge(p, p1);
	}
};

int main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	ds s;
	s.init();
	for(int i = 0; i < m; i++){
		ll a,b;
		cin >> a >> b;	
		s.sett(a, b);
		cout << s.ans << '\n';
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...