Submission #438410

#TimeUsernameProblemLanguageResultExecution timeMemory
438410mango_lassiKeys (IOI21_keys)C++17
100 / 100
2109 ms120008 KiB
#include <vector> #include <bits/stdc++.h> using namespace std; class DSU { private: vector<int> comp, siz; public: DSU(int n) : comp(n), siz(n, 1) { for (int i = 0; i < n; ++i) comp[i] = i; } int getc(int i) { if (comp[i] != i) comp[i] = getc(comp[i]); return comp[i]; } bool join(int a, int b) { a = getc(a); b = getc(b); siz[a] += siz[b]; comp[b] = a; return true; } int compSize(int i) { return siz[getc(i)]; } }; struct Targets { set<int> act_outs, keys; set<pair<int, int>> outs; }; void merge(int i, int t, DSU& dsu, vector<Targets>& tar) { i = dsu.getc(i); t = dsu.getc(t); assert(i != t); // Join smaller to larger int si = tar[i].keys.size() + tar[i].outs.size() + tar[i].act_outs.size(); int st = tar[t].keys.size() + tar[t].outs.size() + tar[t].act_outs.size(); if (si < st) swap(i, t); dsu.join(i, t); // Add new keys for (int key : tar[t].keys) { auto it = tar[i].outs.lower_bound(make_pair(key, 0)); while(it != tar[i].outs.end() && (*it).first == key) { tar[i].act_outs.insert((*it).second); auto tmp = it; ++it; tar[i].outs.erase(tmp); } tar[i].keys.insert(key); } // Add new edges for (int out : tar[t].act_outs) tar[i].act_outs.insert(out); for (auto pr : tar[t].outs) { auto it = tar[i].keys.find(pr.first); if (it != tar[i].keys.end()) tar[i].act_outs.insert(pr.second); else tar[i].outs.insert(pr); } tar[t].act_outs.clear(); tar[t].keys.clear(); tar[t].outs.clear(); } int dfs(int i, vector<int>& state, DSU& dsu, vector<Targets>& tar) { state[i] = 1; // Active while(true) { i = dsu.getc(i); /* cerr << "dfs(" << i << "): "; for (int t : tar[i].act_outs) cerr << t << ' '; cerr << "/ "; for (int x : tar[i].keys) cerr << x << ' '; cerr << "/ "; for (auto pr : tar[i].outs) cerr << pr.first << "," << pr.second << " "; cerr << "\n"; */ if (tar[i].act_outs.empty()) { // cerr << "Done, POTENTIAL SMALLEST\n"; state[i] = -1; // Done, potential smallest return -1; } auto it = tar[i].act_outs.begin(); int t = dsu.getc(*it); tar[i].act_outs.erase(it); // cerr << "Edge " << i << ' ' << t << ": " << state[t] << endl; if (t == i) continue; if (state[t] < 0) { // cerr << "Done, NOT POTENTIAL SMALLEST\n"; state[i] = -2; // Done, NOT potential smallest return -1; } else if (state[t] == 1) { // cerr << "Found cycle!\n"; return t; // Compress cycle } int sub = dfs(t, state, dsu, tar); if (sub >= 0) { bool rec = (dsu.getc(sub) != dsu.getc(i)); merge(i, t, dsu, tar); if (rec) { // cerr << "Found cycle!\n"; return sub; } } else { // cerr << "Done, NOT POTENTIAL SMALLEST\n"; state[i] = -2; // Done, NOT potential smallest return -1; } } } vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) { int n = r.size(); int m = u.size(); vector<Targets> tar(n); for (int i = 0; i < n; ++i) tar[i].keys.insert(r[i]); for (int j = 0; j < m; ++j) { if (c[j] == r[u[j]]) tar[u[j]].act_outs.insert(v[j]); else tar[u[j]].outs.emplace(c[j], v[j]); if (c[j] == r[v[j]]) tar[v[j]].act_outs.insert(u[j]); else tar[v[j]].outs.emplace(c[j], u[j]); } DSU dsu(n); vector<int> state(n, 0); for (int i = 0; i < n; ++i) { if (state[dsu.getc(i)] == 0) dfs(i, state, dsu, tar); } vector<pair<int, int>> ord(n); for (int i = 0; i < n; ++i) ord[i] = {state[dsu.getc(i)] == -1 ? dsu.compSize(i) : n + 1, i}; sort(ord.begin(), ord.end()); vector<int> res(n, 0); for (int i = 0; i < n; ++i) res[ord[i].second] |= (ord[i].first == ord[0].first); return res; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...