結果
問題 | No.399 動的な領主 |
ユーザー | cureskol |
提出日時 | 2023-12-18 17:03:10 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 220 ms / 2,000 ms |
コード長 | 4,205 bytes |
コンパイル時間 | 2,427 ms |
コンパイル使用メモリ | 221,344 KB |
実行使用メモリ | 27,648 KB |
最終ジャッジ日時 | 2024-09-27 08:24:46 |
合計ジャッジ時間 | 6,248 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 3 ms
6,944 KB |
testcase_05 | AC | 19 ms
6,940 KB |
testcase_06 | AC | 220 ms
20,864 KB |
testcase_07 | AC | 218 ms
20,864 KB |
testcase_08 | AC | 208 ms
20,164 KB |
testcase_09 | AC | 207 ms
20,152 KB |
testcase_10 | AC | 4 ms
6,940 KB |
testcase_11 | AC | 16 ms
6,940 KB |
testcase_12 | AC | 173 ms
18,304 KB |
testcase_13 | AC | 173 ms
18,304 KB |
testcase_14 | AC | 144 ms
27,616 KB |
testcase_15 | AC | 146 ms
27,648 KB |
testcase_16 | AC | 152 ms
22,272 KB |
testcase_17 | AC | 208 ms
20,372 KB |
testcase_18 | AC | 201 ms
20,188 KB |
ソースコード
#include <bits/stdc++.h> using ll = long long; struct Tree { int n, root; std::vector<std::vector<int>> son; std::vector<int> parent, depth; Tree(const std::vector<std::vector<int>> &graph, int root = 0) : n(graph.size()), root(root), son(n), parent(n, -1), depth(n, 0) { std::queue<int> que; que.push(root); while (que.size()) { int v = que.front(); que.pop(); for (int c : graph[v]) { if (c == parent[v]) continue; parent[c] = v; son[v].push_back(c); depth[c] = depth[v] + 1; que.push(c); } } } }; class HLD { Tree T; std::vector<int> head, id, id2; int dfs_sz(int v) { int ret = 1, mx_sz = 0; for (int &c : T.son[v]) { int sz = dfs_sz(c); ret += sz; if (mx_sz < sz) { mx_sz = sz; std::swap(T.son[v][0], c); } } return ret; } void dfs_hld(int v, int &k) { id[v] = k++; for (int i = 0; i < T.son[v].size(); i++) { int c = T.son[v][i]; head[c] = (i ? c : head[v]); dfs_hld(c, k); } id2[v] = k; } public: HLD(const Tree &T) : T(T), head(T.n), id(T.n), id2(T.n) { dfs_sz(T.root); int k = 0; dfs_hld(T.root, k); } std::vector<int> get_id() const { return id; } int lca(int u, int v) const { while (head[u] != head[v]) if (T.depth[head[u]] > T.depth[head[v]]) u = T.parent[head[u]]; else v = T.parent[head[v]]; return (T.depth[u] < T.depth[v] ? u : v); } int distance(int u, int v) const { return T.depth[u] + T.depth[v] - T.depth[lca(u, v)] * 2; } // l=lca(u,v) とした時、[u,l] パスと [v,l] パス を閉区間の組みで返す using Interval = std::pair<int, int>; using Path = std::vector<Interval>; std::pair<Path, Path> path(int u, int v) const { Path path_u, path_v; while (head[u] != head[v]) if (T.depth[head[u]] < T.depth[head[v]]) { path_v.emplace_back(id[v], id[head[v]]); v = T.parent[head[v]]; } else { path_u.emplace_back(id[u], id[head[u]]); u = T.parent[head[u]]; } if (u == v) path_u.emplace_back(id[u], id[u]); else { if (T.depth[u] < T.depth[v]) path_v.emplace_back(id[v], id[u]); else path_u.emplace_back(id[u], id[v]); } return {path_u, path_v}; } // [l,r) が v の部分木 Interval subtree(int v) const { return {id[v], id2[v]}; } }; template <typename T> class Imos { std::vector<T> data; public: Imos(int n) : data(n, 0) {} //[l,r) に a を追加 void add(int l, int r, T a = 1) { data[l] += a; if (r < data.size()) data[r] -= a; } std::vector<T> build() { for (int i = 0; i + 1 < data.size(); i++) data[i + 1] += data[i]; return data; } }; int main() { int n; std::cin >> n; std::vector<std::vector<int>> g(n); for (int _ = 1; _ < n; _++) { int u, v; std::cin >> u >> v; u--, v--; g[u].push_back(v); g[v].push_back(u); } Tree t(g); HLD hld(t); Imos<int> imos(n); int q; std::cin >> q; while (q--) { int u, v; std::cin >> u >> v; u--, v--; auto [path_l, path_r] = hld.path(u, v); path_l.insert(path_l.end(), path_r.begin(), path_r.end()); for (const auto [u, v] : path_l) { auto [l, r] = std::minmax(u, v); imos.add(l, r + 1); } } auto sum = imos.build(); ll ans = 0; for (ll x : sum) ans += x * (x + 1) / 2; std::cout << ans << std::endl; }