結果
問題 | No.399 動的な領主 |
ユーザー | uenoku |
提出日時 | 2018-01-19 04:16:43 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,015 ms / 2,000 ms |
コード長 | 8,425 bytes |
コンパイル時間 | 3,233 ms |
コンパイル使用メモリ | 214,268 KB |
実行使用メモリ | 48,624 KB |
最終ジャッジ日時 | 2024-06-06 16:52:35 |
合計ジャッジ時間 | 13,196 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 5 ms
5,376 KB |
testcase_05 | AC | 60 ms
7,020 KB |
testcase_06 | AC | 1,015 ms
38,776 KB |
testcase_07 | AC | 909 ms
38,780 KB |
testcase_08 | AC | 907 ms
38,592 KB |
testcase_09 | AC | 881 ms
38,568 KB |
testcase_10 | AC | 7 ms
5,376 KB |
testcase_11 | AC | 43 ms
7,052 KB |
testcase_12 | AC | 602 ms
37,988 KB |
testcase_13 | AC | 559 ms
38,116 KB |
testcase_14 | AC | 263 ms
48,624 KB |
testcase_15 | AC | 338 ms
48,496 KB |
testcase_16 | AC | 420 ms
42,880 KB |
testcase_17 | AC | 940 ms
38,436 KB |
testcase_18 | AC | 910 ms
38,592 KB |
ソースコード
#include <bits/stdc++.h> #define rep(i, n) for (lli i = 0; i < (n); i++) #define rrep(i, n) for (lli i = (n)-1; i >= 0; i--) using namespace std; using lli = long long int; struct segtree { vector<lli> dat, lazy; int n; lli unit = 0; segtree(int N) { n = 1; while (N > n) { n *= 2; } dat.assign(2 * n - 1, unit); lazy.assign(2 * n - 1, unit); } void eval(int k) { if (lazy[k] == 0) return; dat[k] += lazy[k]; if (n - 1 > k) { lazy[2 * k + 1] += lazy[k] / 2; lazy[2 * k + 2] += lazy[k] / 2; } lazy[k] = 0; } void update(int a, lli x) { add(a, a + 1, x, 0, 0, n); } void add(int a, int b, lli x) { add(a, b, x, 0, 0, n); } void add(int a, int b, lli x, int k, int l, int r) { eval(k); if (b <= l || r <= a) return; if (a <= l && r <= b) { lazy[k] += (r - l) * x; eval(k); } else { add(a, b, x, 2 * k + 1, l, (l + r) / 2); add(a, b, x, 2 * k + 2, (l + r) / 2, r); dat[k] = dat[2 * k + 1] + dat[2 * k + 2]; } } lli query(int a, int b, int k, int l, int r) { eval(k); if (b <= l || r <= a) return 0; if (a <= l and r <= b) return dat[k]; lli vl = query(a, b, 2 * k + 1, l, (l + r) / 2); lli vr = query(a, b, 2 * k + 2, (l + r) / 2, r); return vl + vr; } lli query(int a, int b) { return query(a, b, 0, 0, n); } }; struct hldec { using T = lli; int n; int col = 0; vector<vector<int>> e; vector<vector<int>> heavy; vector<vector<int>> light; vector<vector<T>> cls; vector<T> vers; vector<pair<int, int>> pos; vector<pair<int, int>> par; map<pair<int, int>, int> dict; bool builded = false; vector<segtree> vec_seg; int root = 0; T unit = 0; vector<int> size; T f(T a, T b) { return a + b; } //add hldec(int n, vector<T> vers, int root = 0) : n(n), root(root), vers(vers) { e.assign(n, {}); par.assign(n, make_pair(-1, -1)); heavy.assign(n, {}); light.assign(n, {}); size.assign(n, 0); pos.assign(n, make_pair(-1, -1)); cls.assign(n, {}); } void add(int u, int v) { e[u].push_back(v); e[v].push_back(u); } int sub_tree_size(int cur, int par) { int tmp = 1; for (auto s : e[cur]) { if (par != s) { tmp += sub_tree_size(s, cur); } } size[cur] = tmp; return tmp; } void dfs_label(int cur, int par) { lli idx = -1; lli mem = 0; rep(i, e[cur].size()) { auto s = e[cur][i]; if (s != par) { if (size[s] > mem) { mem = size[s]; idx = i; } } } if (idx == -1) return; rep(i, e[cur].size()) { auto s = e[cur][i]; if (s != par) { if (idx == i) { heavy[cur].push_back(s); } else { light[cur].push_back(s); } dfs_label(s, cur); } } } void edge_labeling() { sub_tree_size(root, -1); dfs_label(root, -1); } void dfs_arrays(int cur, int c) { cls[c].push_back(vers[cur]); int idx = cls[c].size() - 1; pos[cur] = make_pair(c, cls[c].size() - 1); dict[pos[cur]] = cur; for (auto s : heavy[cur]) { dfs_arrays(s, c); } for (auto s : light[cur]) { col++; par[col] = make_pair(c, idx); dfs_arrays(s, col); } } void make_arrays() { dfs_arrays(root, 0); } void build_segtree() { rep(j, cls.size()) { auto& s = cls[j]; int size = s.size(); segtree seg(size); rep(i, size) { seg.update(i, s[i]); } vec_seg.push_back(seg); } } void build(bool opt = false) { edge_labeling(); if (opt) { e.clear(); } cerr << "labeled done" << endl; make_arrays(); cerr << "arrays" << endl; if (opt) { heavy.clear(); light.clear(); } build_segtree(); builded = true; cerr << "seg_build" << endl; } void add(int u, int v, T x) { if (!builded) { cout << "HOGE" << endl; build(); builded = true; } vector<pair<int, int>> hist_u; vector<pair<int, int>> hist_v; rep(j, 2) { int tmp = j == 1 ? u : v; while (true) { int cur_col = pos[tmp].first; if (j) hist_u.push_back(pos[tmp]); else hist_v.push_back(pos[tmp]); if (cur_col == 0) break; tmp = dict[par[cur_col]]; } } int pivot = 0; T ans = unit; set<int> hist_u_set; map<int, int> post; for (auto s : hist_u) { hist_u_set.insert(s.first); post[s.first] = s.second; } rep(i, hist_v.size()) { if (hist_u_set.find(hist_v[i].first) != hist_u_set.end()) { int h = post[hist_v[i].first]; vec_seg[hist_v[i].first].add(min(h, hist_v[i].second), max(h, hist_v[i].second) + 1, x); pivot = hist_v[i].first; break; } } rep(i, hist_u.size()) { if (hist_u[i].first == pivot) break; vec_seg[hist_u[i].first].add(0, hist_u[i].second + 1, x); } rep(i, hist_v.size()) { if (hist_v[i].first == pivot) break; vec_seg[hist_v[i].first].add(0, hist_v[i].second + 1, x); } } T query(int u, int v) { if (!builded) { build(); builded = true; } vector<pair<int, int>> hist_u; vector<pair<int, int>> hist_v; rep(j, 2) { int tmp = j == 1 ? u : v; while (true) { int cur_col = pos[tmp].first; if (j) hist_u.push_back(pos[tmp]); else hist_v.push_back(pos[tmp]); if (cur_col == 0) break; tmp = dict[par[cur_col]]; } } int pivot = 0; T ans = unit; set<int> hist_u_set; map<int, int> post; for (auto s : hist_u) { hist_u_set.insert(s.first); post[s.first] = s.second; } rep(i, hist_v.size()) { if (hist_u_set.find(hist_v[i].first) != hist_u_set.end()) { int h = post[hist_v[i].first]; ans = f(vec_seg[hist_v[i].first].query(min(h, hist_v[i].second), max(h, hist_v[i].second) + 1), ans); pivot = hist_v[i].first; break; } } rep(i, hist_u.size()) { if (hist_u[i].first == pivot) break; ans = f(vec_seg[hist_u[i].first].query(0, hist_u[i].second + 1), ans); } rep(i, hist_v.size()) { if (hist_v[i].first == pivot) break; ans = f(vec_seg[hist_v[i].first].query(0, hist_v[i].second + 1), ans); } return ans; } }; int main() { int n, m; cin >> n; vector<lli> v(n, 0); hldec tr(n, v); rep(i, n - 1) { int u, v; cin >> u >> v, u--, v--; tr.add(u, v); } int q; tr.build(true); cin >> q; lli sum = 0; rep(i, q) { int u, v; cin >> u >> v, u--, v--; tr.add(u, v, 1); sum += tr.query(u, v); } cout << sum << endl; // //cout << tr.query(0,1)<<endl; // cout << tr.query(3, 4) << endl; }; ;