Submission #830075

#TimeUsernameProblemLanguageResultExecution timeMemory
830075PurpleCrayonSplit the Attractions (IOI19_split)C++17
100 / 100
138 ms33812 KiB
#include "split.h" #include <bits/stdc++.h> using namespace std; #define sz(v) int(v.size()) #define ar array typedef long long ll; const int N = 2e5+10, MOD = 1e9+7; struct DSU { vector<int> par, sz; DSU() {} DSU(int n): par(n) { iota(par.begin(), par.end(), 0); sz.assign(n, 1); } int find_set(int v) { return v == par[v] ? v : par[v] = find_set(par[v]); } bool union_sets(int a, int b) { if ((a = find_set(a)) == (b = find_set(b))) return false; if (sz[a] < sz[b]) swap(a, b); par[b] = a, sz[a] += sz[b], sz[b] = 0; return true; } } d; int n, m, sub[N], who[N]; vector<int> adj[N]; vector<int> tree[N], extra[N]; bool vis[N]; void dfs_tree(int c) { vis[c] = 1; for (int nxt : adj[c]) if (!vis[nxt]) { tree[c].push_back(nxt); tree[nxt].push_back(c); dfs_tree(nxt); } } int dfs_sub(int c, int p) { sub[c] = 1; for (int nxt : tree[c]) if (nxt != p) { sub[c] += dfs_sub(nxt, c); } return sub[c]; } int dfs_cent(int c, int p) { for (int nxt : tree[c]) if (nxt != p && sub[nxt] > n / 2) return dfs_cent(nxt, c); return c; } void dfs_who(int c, int p, int cur) { who[c] = cur; for (int nxt : tree[c]) if (nxt != p) { dfs_who(nxt, c, cur); } } bool marked[N]; void dfs_mark(int c, int p) { marked[c] = 1; for (int nxt : tree[c]) if (nxt != p) { dfs_mark(nxt, c); } } vector<int> collect; int sum = 0; void dfs_collect(int c) { vis[c] = 1; if (sum > 0) { sum -= sub[c]; collect.push_back(c); } for (int nxt : extra[c]) if (!vis[nxt]) { dfs_collect(nxt); } } vector<int> ord; bool only[N], has[N]; void dfs_ord(int c) { has[c] = 1; ord.push_back(c); for (int nxt : adj[c]) if (!has[nxt] && only[nxt]) { dfs_ord(nxt); } } vector<int> trim(vector<int> nodes, int cnt) { memset(only, 0, sizeof(only)); memset(has, 0, sizeof(has)); for (int x : nodes) only[x] = 1; ord.clear(); dfs_ord(nodes[0]); ord.resize(cnt); return ord; } vector<int> get_from_mark(const vector<pair<int, int>>& cols) { vector<int> one, two; for (int i = 0; i < n; i++) { if (marked[i]) one.push_back(i); else two.push_back(i); } one = trim(one, cols[0].first); two = trim(two, cols[1].first); vector<int> ans(n, cols[2].second); for (int x : one) ans[x] = cols[0].second; for (int x : two) ans[x] = cols[1].second; return ans; } vector<int> find_split(int _n, int p1, int p2, int p3, vector<int> p, vector<int> q) { n = _n, m = sz(p); for (int i = 0; i < m; i++) { int x = p[i], y = q[i]; adj[x].push_back(y), adj[y].push_back(x); } vector<pair<int, int>> cols(3); cols[0] = {p1, 1}, cols[1] = {p2, 2}, cols[2] = {p3, 3}; sort(cols.begin(), cols.end()); dfs_tree(0); dfs_sub(0, -1); int root = dfs_cent(0, -1); dfs_sub(root, -1); who[root] = -1; for (int nxt : tree[root]) { dfs_who(nxt, root, nxt); } for (int nxt : tree[root]) { if (sub[nxt] >= cols[0].first) { dfs_mark(nxt, root); return get_from_mark(cols); } } for (int i = 0; i < m; i++) { if (who[p[i]] != who[q[i]] && who[p[i]] >= 0 && who[q[i]] >= 0) { extra[who[p[i]]].push_back(who[q[i]]); extra[who[q[i]]].push_back(who[p[i]]); } } memset(vis, 0, sizeof(vis)); for (int nxt : tree[root]) if (!vis[nxt]) { collect.clear(); sum = cols[0].first; dfs_collect(nxt); if (sum > 0) continue; for (int v : collect) dfs_mark(v, root); return get_from_mark(cols); } return vector<int>(n, 0); }
#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...