結果
問題 | No.399 動的な領主 |
ユーザー | cureskol |
提出日時 | 2023-12-18 21:38:53 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 202 ms / 2,000 ms |
コード長 | 4,546 bytes |
コンパイル時間 | 2,749 ms |
コンパイル使用メモリ | 219,420 KB |
実行使用メモリ | 22,408 KB |
最終ジャッジ日時 | 2024-09-27 08:28:31 |
合計ジャッジ時間 | 5,308 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 17 ms
5,376 KB |
testcase_06 | AC | 189 ms
15,384 KB |
testcase_07 | AC | 202 ms
15,368 KB |
testcase_08 | AC | 191 ms
14,680 KB |
testcase_09 | AC | 190 ms
15,196 KB |
testcase_10 | AC | 4 ms
5,376 KB |
testcase_11 | AC | 16 ms
5,376 KB |
testcase_12 | AC | 151 ms
14,464 KB |
testcase_13 | AC | 148 ms
13,668 KB |
testcase_14 | AC | 133 ms
22,376 KB |
testcase_15 | AC | 137 ms
22,408 KB |
testcase_16 | AC | 142 ms
17,240 KB |
testcase_17 | AC | 190 ms
14,564 KB |
testcase_18 | AC | 181 ms
14,684 KB |
ソースコード
#include <bits/stdc++.h> 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].front(), c); } } return ret; } void dfs_hld(int v, int &k) { id[v] = k++; for (int c : T.son[v]) { head[c] = (c == T.son[v].front() ? head[v] : c); 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) { 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) { return T.depth[u] + T.depth[v] - T.depth[lca(u, v)] * 2; } using Interval = std::pair<int, int>; using Path = std::vector<Interval>; // 和がuvパスになるような閉区間の組みを返す Path path(int u, int v) { Path path; while (head[u] != head[v]) { if (T.depth[head[u]] > T.depth[head[v]]) std::swap(u, v); path.emplace_back(id[head[v]], id[v]); v = T.parent[head[v]]; } path.emplace_back(std::minmax(id[u], id[v])); return path; } // l=lca(u,v) とした時、[u,l] パスと [v,l] パス を閉区間の組みで返す // 非可換クエリ用 std::pair<Path, Path> path_ordered(int u, int v) { 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 (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) { 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; } }; std::vector<std::vector<int>> scan_graph(int n, int m, int index = 1) { std::vector<std::vector<int>> g(n); while (m--) { int u, v; std::cin >> u >> v; u -= index, v -= index; g[u].push_back(v); g[v].push_back(u); } return g; } Tree scan_tree(int n, int index = 1) { return Tree(scan_graph(n, n - 1, index)); } using ll = long long; int main() { int n; std::cin >> n; Tree t = scan_tree(n); HLD hld(t); int q; std::cin >> q; Imos<int> imos(n); while (q--) { int u, v; std::cin >> u >> v; u--, v--; auto p = hld.path(u, v); for (const auto &[l, r] : p) 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; }