結果
問題 | No.399 動的な領主 |
ユーザー | kimiyuki |
提出日時 | 2016-07-15 23:51:37 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,159 ms / 2,000 ms |
コード長 | 7,008 bytes |
コンパイル時間 | 1,903 ms |
コンパイル使用メモリ | 92,552 KB |
実行使用メモリ | 43,392 KB |
最終ジャッジ日時 | 2024-11-07 19:15:29 |
合計ジャッジ時間 | 11,747 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 4 ms
5,248 KB |
testcase_05 | AC | 50 ms
5,888 KB |
testcase_06 | AC | 1,159 ms
31,332 KB |
testcase_07 | AC | 1,062 ms
31,460 KB |
testcase_08 | AC | 1,012 ms
33,704 KB |
testcase_09 | AC | 1,019 ms
33,664 KB |
testcase_10 | AC | 5 ms
5,248 KB |
testcase_11 | AC | 30 ms
7,168 KB |
testcase_12 | AC | 557 ms
43,392 KB |
testcase_13 | AC | 530 ms
43,272 KB |
testcase_14 | AC | 405 ms
36,196 KB |
testcase_15 | AC | 575 ms
36,200 KB |
testcase_16 | AC | 641 ms
39,620 KB |
testcase_17 | AC | 963 ms
33,668 KB |
testcase_18 | AC | 971 ms
33,696 KB |
ソースコード
#include <cstdio> #include <vector> #include <map> #include <functional> #include <cmath> #include <cassert> #define repeat(i,n) for (int i = 0; (i) < (n); ++(i)) #define repeat_reverse(i,n) for (int i = (n)-1; (i) >= 0; --(i)) typedef long long ll; using namespace std; struct heavy_light_decomposition_t { int n; // |V'| vector<int> a; // V ->> V' epic vector<vector<int> > path; // V' -> V*, bottom to top order, disjoint union of codomain matchs V vector<map<int,int> > pfind; // V' * V -> int, find in path vector<int> parent; // V' -> V heavy_light_decomposition_t(int v, vector<vector<int> > const & g) { n = 0; a.resize(g.size()); dfs(v, -1, g); } int dfs(int v, int p, vector<vector<int> > const & g) { int heavy_node = -1; int heavy_size = 0; int desc_size = 1; for (int w : g[v]) if (w != p) { int size = dfs(w, v, g); desc_size += size; if (heavy_size < size) { heavy_node = w; heavy_size = size; } } if (heavy_node == -1) { a[v] = n; n += 1; path.emplace_back(); path.back().push_back(v); pfind.emplace_back(); pfind.back()[v] = 0; parent.push_back(p); } else { int i = a[heavy_node]; a[v] = i; pfind[i][v] = path[i].size(); path[i].push_back(v); parent[i] = p; } return desc_size; } }; struct lowest_common_ancestor_t { vector<vector<int> > a; vector<int> depth; lowest_common_ancestor_t(int v, vector<vector<int> > const & g) { int n = g.size(); int l = 1 + floor(log2(n)); a.resize(l); repeat (k,l) a[k].resize(n, -1); depth.resize(n); dfs(v, -1, 0, g, a[0], depth); repeat (k,l-1) { repeat (i,n) { if (a[k][i] != -1) { a[k+1][i] = a[k][a[k][i]]; } } } } static void dfs(int v, int p, int current_depth, vector<vector<int> > const & g, vector<int> & parent, vector<int> & depth) { parent[v] = p; depth[v] = current_depth; for (int w : g[v]) if (w != p) { dfs(w, v, current_depth + 1, g, parent, depth); } } // find lca of x, y int operator () (int x, int y) const { // O(log N) int l = a.size(); if (depth[x] < depth[y]) swap(x,y); repeat_reverse (k,l) { if (a[k][x] != -1 and depth[a[k][x]] >= depth[y]) { x = a[k][x]; } } assert (depth[x] == depth[y]); assert (x != -1); if (x == y) return x; repeat_reverse (k,l) { if (a[k][x] != a[k][y]) { x = a[k][x]; y = a[k][y]; } } assert (x != y); assert (a[0][x] == a[0][y]); return a[0][x]; } // find the descendant of x for y int descendant (int x, int y) const { assert (depth[x] < depth[y]); int l = a.size(); repeat_reverse (k,l) { if (a[k][y] != -1 and depth[a[k][y]] >= depth[x]+1) { y = a[k][y]; } } assert (a[0][y] == x); return y; } }; struct segment_tree { int n; vector<ll> a, b; explicit segment_tree(int a_n) { n = pow(2,ceil(log2(a_n))); a.resize(2*n-1); // fill 0, unit of add b.resize(2*n-1); // fill 0, unit of sum } void range_add(int l, int r, int z) { range_add(0, 0, n, l, r, z); } void range_add(int i, int il, int ir, int l, int r, int z) { if (l <= il and ir <= r) { a[i] += z; b[i] += z * (ir - il); } else if (ir <= l or r <= il) { // nop } else { range_add(2*i+1, il, (il+ir)/2, l, r, z); range_add(2*i+2, (il+ir)/2, ir, l, r, z); b[i] = a[i] * (ir - il) + b[2*i+1] + b[2*i+2]; } } ll range_sum(int l, int r) { return range_sum(0, 0, n, l, r); } ll range_sum(int i, int il, int ir, int l, int r) { if (l <= il and ir <= r) { return b[i]; } else if (ir <= l or r <= il) { return 0; // unit } else { return a[i] * (min(ir,r) - max(il,l)) + range_sum(2*i+1, il, (il+ir)/2, l, r) + range_sum(2*i+2, (il+ir)/2, ir, l, r); } } }; ll path_sum(heavy_light_decomposition_t & hl, vector<segment_tree> & sts, int v, int w) { ll acc = 0; int i = hl.a[v]; if (hl.a[w] == i) { assert (hl.pfind[i][v] <= hl.pfind[i][w]); // v must be a descendant of w acc += sts[i].range_sum(hl.pfind[i][v], hl.pfind[i][w]+1); } else { acc += sts[i].range_sum(hl.pfind[i][v], hl.path[i].size()); acc += path_sum(hl, sts, hl.parent[i], w); } return acc; } ll path_sum(heavy_light_decomposition_t & hl, lowest_common_ancestor_t & lca, vector<segment_tree> & sts, int x, int y) { int z = lca(x, y); ll acc = 0; if (x != z) acc += path_sum(hl, sts, x, lca.descendant(z, x)); if (y != z) acc += path_sum(hl, sts, y, lca.descendant(z, y)); acc += path_sum(hl, sts, z, z); return acc; } void path_add(heavy_light_decomposition_t & hl, vector<segment_tree> & sts, int v, int w, int delta) { int i = hl.a[v]; if (hl.a[w] == i) { assert (hl.pfind[i][v] <= hl.pfind[i][w]); // v must be a descendant of w sts[i].range_add(hl.pfind[i][v], hl.pfind[i][w]+1, delta); } else { sts[i].range_add(hl.pfind[i][v], hl.path[i].size(), delta); path_add(hl, sts, hl.parent[i], w, delta); } } void path_add(heavy_light_decomposition_t & hl, lowest_common_ancestor_t & lca, vector<segment_tree> & sts, int x, int y, int delta) { int z = lca(x, y); if (x != z) path_add(hl, sts, x, lca.descendant(z, x), delta); if (y != z) path_add(hl, sts, y, lca.descendant(z, y), delta); path_add(hl, sts, z, z, delta); } int main() { // input int n; scanf("%d", &n); vector<vector<int> > g(n); repeat (i,n-1) { int a, b; scanf("%d%d", &a, &b); -- a; -- b; g[a].push_back(b); g[b].push_back(a); } // prepare const int root = 0; heavy_light_decomposition_t hl(root, g); vector<segment_tree> sts; repeat (i,hl.n) { sts.emplace_back(hl.path[i].size()); } repeat (i,n) { int l = hl.a[i]; sts[l].range_add(hl.pfind[l][i], hl.pfind[l][i]+1, 1); } lowest_common_ancestor_t lca(root, g); // run ll ans = 0; int q; scanf("%d", &q); repeat (i,q) { int a, b; scanf("%d%d", &a, &b); -- a; -- b; ans += path_sum(hl, lca, sts, a, b); path_add(hl, lca, sts, a, b, 1); } // output printf("%lld\n", ans); return 0; }