Submission #1271343

#TimeUsernameProblemLanguageResultExecution timeMemory
1271343VMaksimoski008Making Friends on Joitter is Fun (JOI20_joitter2)C++20
0 / 100
19 ms42564 KiB
#include <bits/stdc++.h> #define ar array //#define int long long using namespace std; using ll = long long; using pii = pair<int, int>; using pll = pair<ll, ll>; const int mod = 1e9 + 7; const ll inf = 1e18; const int N = 3e5 + 5; set<int> st[N], in[N], out[N]; inline ll f(ll x) { return x * (x - 1); } struct union_find { int n; vector<int> par, size; vector<pii> ord; ll ans = 0; union_find(int _n) : n(_n), par(n+1), size(n+1, 1) { for(int i=1; i<=n; i++) par[i] = i; } int find(int u) { if(u == par[u]) return u; return par[u] = find(par[u]); } void uni(int a, int b) { a = find(a); b = find(b); if(a == b) return ; if(size[a] < size[b]) swap(a, b); //samo vo starite ans -= (f(size[a]) + f(size[b])); //koga ke se spojat ans += f(size[a]+size[b]); if(a == 3 && b == 5) { // cout << size[a] << " " << size[b] << endl; // cout << "rem: " << f(size[a])+f(size[b]) << endl; // cout << "add: " << f(size[a]+size[b]) << endl; } // cout << "after p1: " << ans << endl; //directed edges set<int> vis; for(auto u : st[a]) { if(same_set(u, a)) continue; // vis.insert(u); // if(!same_set(b, u)) ans += size[b]; // else ans -= size[a]; if(!st[b].count(u)) { // if(a==3&&b==5)cout << "dir " << u << " to " << a << endl; if(!same_set(b, u)) ans += size[b]; else ans -= size[a]; } } for(auto u : st[b]) { if(same_set(u, b)) continue; // if(a==3&&b==5)cout << "dir " << u << " to " << b << endl; // vis.insert(u); // if(!same_set(a, u)) ans += size[a]; // else ans -= size[b]; if(!st[a].count(u)) { // if(a==3&&b==5)cout << "dir " << u << " to " << a << endl; if(!same_set(a, u)) ans += size[a]; else ans -= size[b]; } } // cout << "after p2: " << ans << endl; if(out[a].count(b)) out[a].erase(b); if(out[b].count(a)) out[b].erase(a); if(in[a].count(b)) in[a].erase(b); if(in[b].count(a)) in[b].erase(a); for(int u : out[b]) { in[u].erase(b); add_edge_g(a, u); } for(int u : in[b]) { out[u].erase(b); add_edge_g(u, a); } for(int u : st[b]) { if(!same_set(u, a)) st[a].insert(u); } vector<int> to_rem; for(int u : st[a]) if(same_set(u, b)) to_rem.push_back(u); for(int u : to_rem) st[a].erase(u); par[b] = a; size[a] += size[b]; } void check(int a, int b) { if(same_set(a, b)) return ; if(in_comp(b, a)) return ; ans += get_size(b); add_edge_st(b, a); add_edge_g(a, b); while(!ord.empty()) { auto [u, v] = ord.back(); uni(u, v); ord.pop_back(); } } void add_edge_g(int a, int b) { a = find(a); b = find(b); out[a].insert(b); in[b].insert(a); if(out[a].count(b) && out[b].count(a)) ord.push_back({ a, b }); } void add_edge_st(int a, int b) { st[find(a)].insert(b); } bool in_comp(int a, int b) { return st[find(a)].count(b); } int get_size(int a) { return size[find(a)]; } bool same_set(int a, int b) { return find(a) == find(b); } void print() { // for(int i=1; i<=n; i++) cout << par[i] << " "; // cout << endl; // cout << "print st: \n"; // for(int i=1; i<=n; i++) { // if(i != find(i)) continue; // cout << i << ": "; // for(int j : st[i]) cout << j << " "; // cout << endl; // } // cout << "print in: \n"; // for(int i=1; i<=n; i++) { // if(i != find(i)) continue; // cout << i << ": "; // for(int j : in[i]) cout << j << " "; // cout << endl; // } // cout << "print out: \n"; // for(int i=1; i<=n; i++) { // if(i != find(i)) continue; // cout << i << ": "; // for(int j : out[i]) cout << j << " "; // cout << endl; // } } }; signed main() { ios_base::sync_with_stdio(false); cout.tie(0); cin.tie(0); int n, m; cin >> n >> m; union_find dsu(n); while(m--) { int a, b; cin >> a >> b; dsu.check(a, b); dsu.print(); cout << dsu.ans << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...