제출 #1126798

#제출 시각아이디문제언어결과실행 시간메모리
1126798PanndaRigged Roads (NOI19_riggedroads)C++20
100 / 100
309 ms145676 KiB
#include <bits/stdc++.h> using namespace std; struct Tree { vector<int> depth, parent, siz, head, begin, end; Tree(int n, const vector<vector<int>> &adj) : depth(n), parent(n), siz(n), head(n), begin(n), end(n) { auto scout = [&](auto self, int u, int p) -> void { depth[u] = p == -1 ? 0 : depth[p] + 1; parent[u] = p; siz[u] = 1; for (int v : adj[u]) { if (v == p) continue; self(self, v, u); siz[u] += siz[v]; } }; scout(scout, 0, -1); int tim = 0; auto decompose = [&](auto self, int u, int h) -> void { head[u] = h; begin[u] = tim++; int heavy = -1; for (int v : adj[u]) { if (v == parent[u]) continue; if (heavy == -1 || siz[v] > siz[heavy]) heavy = v; } if (heavy != -1) { self(self, heavy, h); } for (int v : adj[u]) { if (v == parent[u] || v == heavy) continue; self(self, v, v); } end[u] = tim; }; decompose(decompose, 0, 0); } int getDepth(int u) { return depth[u]; } int getNode(int u) { return begin[u]; } vector<array<int, 2>> getPath(int u, int v, bool includeLCA = true) { vector<array<int, 2>> res; while (head[u] != head[v]) { if (depth[head[u]] > depth[head[v]]) swap(u, v); res.push_back({ begin[head[v]], begin[v] + 1 }); v = parent[head[v]]; } if (depth[u] > depth[v]) swap(u, v); int l = begin[u] + (!includeLCA); int r = begin[v] + 1; if (l < r) res.push_back({l, r}); return res; } }; struct Paint { int n; vector<int> color; Paint(int n, int c0 = -1) : n(n), color(4 * n, c0) {} void paint(int ql, int qr, int c) { auto dfs = [&](auto self, int idx, int l, int r) -> void { if (r <= ql || qr <= l) return; if (ql <= l && r <= qr) { color[idx] = c; return; } if (color[idx] != -1) { color[2 * idx + 1] = color[2 * idx + 2] = color[idx]; color[idx] = -1; } int m = (l + r) >> 1; self(self, 2 * idx + 1, l, m); self(self, 2 * idx + 2, m, r); }; dfs(dfs, 0, 0, n); } int getColor(int i) { int idx = 0, l = 0, r = n; while (l + 1 < r) { if (color[idx] != -1) return color[idx]; int m = (l + r) >> 1; if (i < m) { idx = 2 * idx + 1; r = m; } else { idx = 2 * idx + 2; l = m; } } return color[idx]; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<array<int, 2>> edges(m); for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; u--; v--; edges[i] = {u, v}; } vector<bool> is_tree_edge(m, false); for (int i = 0; i < n - 1; i++) { int p; cin >> p; p--; is_tree_edge[p] = true; } vector<vector<int>> adj(n); for (int i = 0; i < m; i++) { if (!is_tree_edge[i]) continue; auto [u, v] = edges[i]; adj[u].push_back(v); adj[v].push_back(u); } Tree tree(n, adj); Paint paint(n, -1); for (int i = m - 1; i >= 0; i--) { if (is_tree_edge[i]) continue; auto [u, v] = edges[i]; for (auto [l, r] : tree.getPath(u, v, false)) { paint.paint(l, r, i); } } vector<vector<int>> inbox(m); for (int i = 0; i < m; i++) { if (!is_tree_edge[i]) continue; auto [u, v] = edges[i]; if (tree.getDepth(u) > tree.getDepth(v)) swap(u, v); int color = paint.getColor(tree.getNode(v)); if (color != -1) inbox[color].push_back(i); } int val = 1; vector<int> w(m, -1); for (int i = 0; i < m; i++) { if (!is_tree_edge[i]) { sort(inbox[i].begin(), inbox[i].end()); for (int j : inbox[i]) { if (w[j] == -1) w[j] = val++; } w[i] = val++; } else { auto [u, v] = edges[i]; if (tree.getDepth(u) > tree.getDepth(v)) swap(u, v); int color = paint.getColor(tree.getNode(v)); if (color == -1 || color > i) { w[i] = val++; } } } for (int i = 0; i < m; i++) { cout << w[i] << " \n"[i == m - 1]; } }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...