結果
問題 | No.399 動的な領主 |
ユーザー | myun-plusplus |
提出日時 | 2020-12-15 17:35:53 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 12,679 bytes |
コンパイル時間 | 2,403 ms |
コンパイル使用メモリ | 213,832 KB |
実行使用メモリ | 22,296 KB |
最終ジャッジ日時 | 2024-09-20 01:49:02 |
合計ジャッジ時間 | 8,841 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
13,760 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 3 ms
6,940 KB |
testcase_05 | AC | 23 ms
6,944 KB |
testcase_06 | AC | 289 ms
13,404 KB |
testcase_07 | AC | 299 ms
13,464 KB |
testcase_08 | AC | 288 ms
13,392 KB |
testcase_09 | AC | 282 ms
13,484 KB |
testcase_10 | AC | 4 ms
6,944 KB |
testcase_11 | AC | 15 ms
6,944 KB |
testcase_12 | AC | 174 ms
13,984 KB |
testcase_13 | AC | 161 ms
13,864 KB |
testcase_14 | AC | 60 ms
17,588 KB |
testcase_15 | AC | 138 ms
17,512 KB |
testcase_16 | TLE | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
ソースコード
//#define ATCODER_EX_DEBUG #include <type_traits> #include <utility> #include <vector> #include <cstddef> #include <iostream> namespace atcoder_ex { template<bool Is_Evertable = false, class S = std::nullptr_t, S(*op)(S, S) = nullptr, S(*e)() = nullptr, class F = std::nullptr_t, S(*mapping)(F, S) = nullptr, F(*composition)(F, F) = nullptr, F(*id)() = nullptr> class link_cut_tree { static constexpr bool is_pull_type_v = !std::is_same_v<S, std::nullptr_t>; static constexpr bool is_push_type_v = !std::is_same_v<F, std::nullptr_t>; struct no_value_base {}; struct sum_base { sum_base() : value(e()), sum(e()) {} S value, sum; }; struct sum_apply_base { sum_apply_base() : value(e()), sum(e()), apply(id()) {} S value, sum; F apply; }; struct non_evertable_base {}; struct evertable_base { evertable_base() : rev(false) {} bool rev; }; using v_base = std::conditional_t<is_push_type_v, sum_apply_base, std::conditional_t<is_pull_type_v, sum_base, no_value_base>>; using e_base = std::conditional_t<Is_Evertable, evertable_base, non_evertable_base>; struct splay_tree_node : public v_base, public e_base { splay_tree_node() : v_base(), e_base(), left(-1), right(-1), parent(-1) {} int left, right, parent; }; using node = splay_tree_node; public: link_cut_tree() : link_cut_tree(0) {} explicit link_cut_tree(int n) : m_size(n), m_nodes(n) {} void link(int v, int p) { expose(v); splay(v); expose(p); splay(v); m_nodes[p].right = v; m_nodes[v].parent = p; pull(p); } void cut(int v) { expose(v); splay(v); int p = m_nodes[v].left; m_nodes[v].left = -1; m_nodes[p].parent = -1; pull(v); } template<bool Always_True = true, std::enable_if_t<Always_True && Is_Evertable>* = nullptr> void evert(int v) { expose(v); splay(v); std::swap(m_nodes[v].left, m_nodes[v].right); m_nodes[v].rev = true; } int lowest_common_ancester(int u, int v) { expose(u); return expose(v); } template<bool Always_True = true, std::enable_if_t<Always_True && is_pull_type_v>* = nullptr> S get(int v) { push_down_from_top(v); splay(v); return m_nodes[v].value; } template<bool Always_True = true, std::enable_if_t<Always_True && is_pull_type_v>* = nullptr> void set(int v, S x) { push_down_from_top(v); splay(v); m_nodes[v].value = x; pull(v); } template<bool Always_True = true, std::enable_if_t<Always_True && is_pull_type_v>* = nullptr> S prod(int u, int v) { expose(u); int w = expose(v); splay(u); splay(w); S sum = m_nodes[w].value; if (u != w) { sum = op(m_nodes[u].sum, sum); } if (int r = m_nodes[w].right; r != -1) { sum = op(sum, m_nodes[r].sum); } return sum; } template<bool Always_True = true, std::enable_if_t<Always_True && is_push_type_v>* = nullptr> void apply(int v, F f) { push_down_from_top(v); m_nodes[v].value = mapping(f, m_nodes[v].value); pull_to_top(v); } template<bool Always_True = true, std::enable_if_t<Always_True && is_push_type_v>* = nullptr> void apply(int u, int v, F f) { expose(u); int w = expose(v); splay(u); splay(w); m_nodes[w].value = mapping(f, m_nodes[w].value); if (u != w) { apply_to_node(u, f); } if (int r = m_nodes[w].right; r != -1) { apply_to_node(r, f); } } void debug() { std::vector<bool> visited(m_size); auto dfs = [&](auto self, int v, int p) -> void { visited[v] = true; S sum = m_nodes[v].value; if (int l = m_nodes[v].left; l != -1) { self(self, l, v); sum = op(m_nodes[l].sum, sum); } if (int r = m_nodes[v].right; r != -1) { self(self, r, v); sum = op(sum, m_nodes[r].sum); } bool ok = m_nodes[v].sum == sum; if (!ok) { std::cout << v << std::endl; } }; for (int v = 0; v < m_size; ++v) { if (visited[v]) continue; if (!is_splay_tree_root(v)) continue; dfs(dfs, v, -1); } } private: int expose(int v) { int pre = -1; for (int current = v; current != -1; current = m_nodes[current].parent) { push_down_from_top(current); splay(current); m_nodes[current].right = pre; pull(current); pre = current; } return pre; } void splay(int v) { while (!is_splay_tree_root(v)) { int p = m_nodes[v].parent; int gp = m_nodes[p].parent; if (!is_splay_tree_root(p)) { int ggp = m_nodes[gp].parent; if (ggp != -1) { if (gp == m_nodes[ggp].left) m_nodes[ggp].left = v; else if (gp == m_nodes[ggp].right) m_nodes[ggp].right = v; } m_nodes[v].parent = ggp; if (v == m_nodes[p].left && p == m_nodes[gp].right) { int b = m_nodes[v].right, c = m_nodes[v].left; m_nodes[v].right = p; m_nodes[p].parent = v; m_nodes[v].left = gp; m_nodes[gp].parent = v; m_nodes[p].left = b; if (b != -1) m_nodes[b].parent = p; m_nodes[gp].right = c; if (c != -1) m_nodes[c].parent = gp; } else if (v == m_nodes[p].right && p == m_nodes[gp].left) { int b = m_nodes[v].left, c = m_nodes[v].right; m_nodes[v].left = p; m_nodes[p].parent = v; m_nodes[v].right = gp; m_nodes[gp].parent = v; m_nodes[p].right = b; if (b != -1) m_nodes[b].parent = p; m_nodes[gp].left = c; if (c != -1) m_nodes[c].parent = gp; } else if (v == m_nodes[p].left && p == m_nodes[gp].left) { int b = m_nodes[v].right, c = m_nodes[p].right; m_nodes[v].right = p; m_nodes[p].parent = v; m_nodes[p].right = gp; m_nodes[gp].parent = p; m_nodes[p].left = b; if (b != -1) m_nodes[b].parent = p; m_nodes[gp].left = c; if (c != -1) m_nodes[c].parent = gp; } else { int b = m_nodes[v].left, c = m_nodes[p].left; m_nodes[v].left = p; m_nodes[p].parent = v; m_nodes[p].left = gp; m_nodes[gp].parent = p; m_nodes[p].right = b; if (b != -1) m_nodes[b].parent = p; m_nodes[gp].right = c; if (c != -1) m_nodes[c].parent = gp; } pull(gp); pull(p); pull(v); } else { if (v == m_nodes[p].left) { int x = m_nodes[v].right; m_nodes[p].left = x; if (x != -1) m_nodes[x].parent = p; m_nodes[v].parent = m_nodes[p].parent; m_nodes[v].right = p; m_nodes[p].parent = v; } else { int x = m_nodes[v].left; m_nodes[p].right = x; if (x != -1) m_nodes[x].parent = p; m_nodes[v].parent = m_nodes[p].parent; m_nodes[v].left = p; m_nodes[p].parent = v; } pull(p); pull(v); } } } inline int is_splay_tree_root(int v) const { int p = m_nodes[v].parent; return p == -1 || (m_nodes[p].left != v && m_nodes[p].right != v); } template<bool Always_True = true, std::enable_if_t<Always_True && is_pull_type_v>* = nullptr> inline void pull(int v) { S sum = m_nodes[v].value; if (int l = m_nodes[v].left; l != -1) sum = op(m_nodes[l].sum, sum); if (int r = m_nodes[v].right; r != -1) sum = op(sum, m_nodes[r].sum); m_nodes[v].sum = sum; } template<bool Always_True = true, std::enable_if_t<Always_True && !is_pull_type_v>* = nullptr> inline void pull(int) {} template<bool Always_True = true, std::enable_if_t<Always_True && is_push_type_v>* = nullptr> inline void update_push(int v) { pull(v); } template<bool Always_True = true, std::enable_if_t<Always_True && !is_push_type_v>* = nullptr> inline void update_push(int) {} template<bool Always_True = true, std::enable_if_t<Always_True && is_push_type_v>* = nullptr> inline void push(int v) { if (m_nodes[v].apply == id()) return; if (int l = m_nodes[v].left; l != -1) { apply_to_node(l, m_nodes[v].apply); } if (int r = m_nodes[v].right; r != -1) { apply_to_node(r, m_nodes[v].apply); } m_nodes[v].apply = id(); if constexpr (Is_Evertable) { eval_rev(v); } } template<bool Always_True = true, std::enable_if_t<Always_True && !is_push_type_v>* = nullptr> inline void push(int v) { if constexpr (Is_Evertable) { eval_rev(v); } } template<bool Always_True = true, std::enable_if_t<Always_True&& is_push_type_v>* = nullptr> inline void apply_to_node(int v, F f) { m_nodes[v].value = mapping(f, m_nodes[v].value); m_nodes[v].sum = mapping(f, m_nodes[v].sum); m_nodes[v].apply = composition(f, m_nodes[v].apply); } template<bool Always_True = true, std::enable_if_t<Always_True && Is_Evertable>* = nullptr> inline void eval_rev(int v) { if (m_nodes[v].rev) { if (int l = m_nodes[v].left; l != -1) { std::swap(m_nodes[l].left, m_nodes[l].right); m_nodes[l].rev = true; } if (int r = m_nodes[v].right; r != -1) { std::swap(m_nodes[r].left, m_nodes[r].right); m_nodes[r].rev = true; } m_nodes[v].rev = false; } } template<bool Always_True = true, std::enable_if_t<Always_True && !Is_Evertable>* = nullptr> inline void eval_rev(int v) {} void pull_to_top(int v) { while (v != -1) { pull(v); v = m_nodes[v].parent; } } void update_push_to_top(int v) { while (v != -1) { update_push(v); v = m_nodes[v].parent; } } void push_down_from_top(int v) { if (m_nodes[v].parent != -1) { push_down_from_top(m_nodes[v].parent); } push(v); } private: int m_size; std::vector<node> m_nodes; }; } // namespace atcoder_ex #include <bits/stdc++.h> using namespace std; using ll = long long; using P = std::pair<ll, int>; constexpr P op(P l, P r) { return P(l.first + r.first, l.second + r.second); } constexpr P e() { return P(0, 1); } constexpr P mapping(int l, P r) { return P(r.first + (ll)l * r.second, r.second); } constexpr int composition(int l, int r) { return l + r; } constexpr int id() { return 0; } int main() { std::cin.tie(0); std::ios::sync_with_stdio(0); int N; cin >> N; vector<vector<int>> tree(N); for (int i = 0; i < N - 1; ++i) { int u, v; cin >> u >> v; u--; v--; tree[u].push_back(v); tree[v].push_back(u); } atcoder_ex::link_cut_tree<false, P, op, e, int, mapping, composition, id> lct(N); auto dfs = [&](auto self, int v, int p) -> void { for (int u : tree[v]) { if (u == p) continue; lct.link(u, v); self(self, u, v); } }; dfs(dfs, 0, -1); int Q; cin >> Q; ll ans = 0; for (int i = 0; i < Q; ++i) { int a, b; cin >> a >> b; a--; b--; lct.apply(a, b, 1); ans += lct.prod(a, b).first; } cout << ans << endl; }