結果
問題 | No.901 K-ary εxtrεεmε |
ユーザー | lumc_ |
提出日時 | 2019-10-04 22:29:22 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 182 ms / 3,000 ms |
コード長 | 7,602 bytes |
コンパイル時間 | 1,755 ms |
コンパイル使用メモリ | 127,680 KB |
実行使用メモリ | 40,536 KB |
最終ジャッジ日時 | 2024-10-04 06:21:54 |
合計ジャッジ時間 | 6,566 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 104 ms
40,536 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 3 ms
5,248 KB |
testcase_03 | AC | 3 ms
5,248 KB |
testcase_04 | AC | 3 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 2 ms
5,248 KB |
testcase_07 | AC | 146 ms
36,436 KB |
testcase_08 | AC | 140 ms
36,436 KB |
testcase_09 | AC | 147 ms
36,568 KB |
testcase_10 | AC | 150 ms
36,440 KB |
testcase_11 | AC | 150 ms
36,444 KB |
testcase_12 | AC | 139 ms
36,440 KB |
testcase_13 | AC | 136 ms
36,444 KB |
testcase_14 | AC | 142 ms
36,436 KB |
testcase_15 | AC | 145 ms
36,440 KB |
testcase_16 | AC | 156 ms
36,440 KB |
testcase_17 | AC | 139 ms
36,440 KB |
testcase_18 | AC | 140 ms
36,436 KB |
testcase_19 | AC | 179 ms
36,440 KB |
testcase_20 | AC | 135 ms
36,436 KB |
testcase_21 | AC | 146 ms
36,440 KB |
testcase_22 | AC | 182 ms
36,312 KB |
testcase_23 | AC | 135 ms
36,436 KB |
testcase_24 | AC | 146 ms
36,436 KB |
testcase_25 | AC | 139 ms
36,440 KB |
testcase_26 | AC | 155 ms
36,572 KB |
testcase_27 | AC | 130 ms
36,440 KB |
testcase_28 | AC | 132 ms
36,436 KB |
testcase_29 | AC | 127 ms
36,412 KB |
ソースコード
// includes {{{ #include<iostream> #include<iomanip> #include<algorithm> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #include<tuple> #include<cmath> #include<random> #include<cassert> #include<bitset> #include<cstdlib> // #include<deque> // #include<multiset> // #include<cstring> // #include<bits/stdc++.h> // }}} using namespace std; using ll = long long; // DoublingTree ( <tree> , initial? ) // .addEdge(a, b) // .set(i, val) or .assign( <data> ) // === initiation === // when single tree : .build(root = 0) // when forest : .dfs(roots) & .init() // === query === // .lca(a, b) // .fold(hi, a, hi_inclusive = true) // .climb(from, steps) // .descendTo(from, to, steps) // === --- === // .depth[a] // .par[i][a] // climb 2^i times from [a] // .dat[i][a] // apply to 2^i edges from [a] to ancestor /// --- Doubilng Tree {{{ /// #include <cassert> #include <iterator> #include <vector> template < class Monoid > struct DoublingTree { using T = typename Monoid::T; size_t n; int logn; vector< vector< int > > tree; vector< int > depth; // 0-indexed // [logn][n] vector< vector< int > > par; vector< vector< T > > dat; int log(int n) { int h = 1; while((1 << h) < n) h++; return h; } DoublingTree() : n(0) {} DoublingTree(size_t n, const T &initial = Monoid::identity()) : n(n), logn(log(n)), tree(n), depth(n), par(logn, vector< int >(n)), dat(logn, vector< T >(n, initial)) {} template < class InputIter, class = typename iterator_traits< InputIter >::value_type > DoublingTree(InputIter first, InputIter last, const T &initial = Monoid::identity()) : DoublingTree(distance(first, last), initial) { copy(first, last, begin(tree)); } DoublingTree(const vector< vector< int > > &tree, const T &initial = Monoid::identity()) : DoublingTree(begin(tree), end(tree), initial) {} void addEdge(size_t a, size_t b) { assert(a < n && b < n); tree[a].push_back(b); tree[b].push_back(a); } void set(size_t i, const T &val) { assert(i < n); dat[0][i] = val; } template < class InputIter, class = typename iterator_traits< InputIter >::value_type > void assign(InputIter first, InputIter last) { assert(distance(first, last) <= n); copy(first, last, begin(dat[0])); } template < class T > void build(const vector< T > &roots) { for(T &root : roots) dfs(root); init(); } void build(size_t root = 0) { assert(root < n); dfs(root); init(); } bool initiated = 0; void init() { assert(!initiated); initiated = 1; for(int k = 1; k < logn; k++) { for(size_t i = 0; i < n; i++) { int p = par[k - 1][i]; if(p == -1) { par[k][i] = -1; continue; } dat[k][i] = Monoid::op(dat[k - 1][p], dat[k - 1][i]); par[k][i] = par[k - 1][p]; } } } void dfs(size_t i, int p = -1, int d = 0) { assert(i < n); depth[i] = d; par[0][i] = p; for(int j : tree[i]) if(j != p) { dfs(j, i, d + 1); } } int climb(size_t a, ll steps) { assert(initiated); assert(a < n); for(int i = logn - 1; i >= 0 && a != -1; i--) if(steps >= (1 << i)) a = par[i][a], steps -= 1 << i; assert(a == -1 || steps == 0); return a; } int descendTo(size_t from, size_t to, ll steps = 1) { assert(initiated); assert(from < n && to < n); assert(depth[to] >= depth[from]); int up = depth[to] - depth[from] - steps; if(up < 0) up = 0; return climb(to, up); } int steps(size_t from, size_t to) { assert(initiated); assert(from < n && to < n); return depth[from] + depth[to] - depth[lca(from, to)] * 2; } int lca(size_t a, size_t b) { assert(initiated); assert(a < n && b < n); if(depth[a] < depth[b]) swap(a, b); for(int k = logn - 1; k >= 0; k--) { int na = par[k][a]; if(na == -1 || depth[na] < depth[b]) continue; a = na; } if(a == b) return a; for(int k = logn - 1; k >= 0; k--) { int na = par[k][a]; int nb = par[k][b]; if(na == nb) continue; a = na, b = nb; } return par[0][a]; } T fold(size_t hi, size_t a, bool inclusive = true) { assert(initiated); assert(hi < n && a < n); T res = Monoid::identity(); for(int k = logn - 1; k >= 0; k--) { int na = par[k][a]; if(na == -1 || depth[na] < depth[hi]) continue; res = Monoid::op(dat[k][a], res); a = na; } if(inclusive) res = Monoid::op(dat[0][hi], res); return res; } int size() { return n; } }; /// }}}--- /// /// --- Monoid examples {{{ /// constexpr long long inf_monoid = 1e18 + 100; #include <algorithm> struct Nothing { using T = char; using Monoid = Nothing; using M = T; static constexpr T op(const T &, const T &) { return T(); } static constexpr T identity() { return T(); } template < class X > static constexpr X actInto(const M &, long long, const X &x) { return x; } }; template < class U = long long > struct RangeMin { using T = U; static T op(const T &a, const T &b) { return std::min< T >(a, b); } static constexpr T identity() { return T(inf_monoid); } }; template < class U = long long > struct RangeMax { using T = U; static T op(const T &a, const T &b) { return std::max< T >(a, b); } static constexpr T identity() { return T(-inf_monoid); } }; template < class U = long long > struct RangeSum { using T = U; static T op(const T &a, const T &b) { return a + b; } static constexpr T identity() { return T(0); } }; template < class U > struct RangeProd { using T = U; static T op(const T &a, const T &b) { return a * b; } static constexpr T identity() { return T(1); } }; template < class U = long long > struct RangeOr { using T = U; static T op(const T &a, const T &b) { return a | b; } static constexpr T identity() { return T(0); } }; #include <bitset> template < class U = long long > struct RangeAnd { using T = U; static T op(const T &a, const T &b) { return a & b; } static constexpr T identity() { return T(-1); } }; template < size_t N > struct RangeAnd< std::bitset< N > > { using T = std::bitset< N >; static T op(const T &a, const T &b) { return a & b; } static constexpr T identity() { return std::bitset< N >().set(); } }; /// }}}--- /// using DBL = DoublingTree< RangeSum<> >; const int N = 1e5; std::vector<std::vector<pair<int, int>>> g; int n; int val[N]; int in[N], out[N]; int id = 0; void dfs(int i, int p = -1) { in[i] = id++; for(auto to : g[i]) if(to.first != p) { int j, w; tie(j, w) = to; dfs(j, i); val[j] = w; } out[i] = id; } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0); cin >> n; g.resize(n); DBL dbl(n); for(int i = 0; i < n - 1; i++) { int a, b, w; std::cin >> a >> b >> w; g[a].emplace_back(b, w); g[b].emplace_back(a, w); dbl.addEdge(a, b); } dfs(0); for(int i = 0; i < n; i++) dbl.set(i, val[i]); dbl.build(0); int q; cin >> q; for(int i = 0; i < q; i++) { int k; cin >> k; vector<int> x(k); for(int j = 0; j < k; j++) cin >> x[j]; sort(begin(x), end(x), [&](int a, int b) { return in[a] < in[b];} ); ll ans = 0; int lowest = x[0]; for(int j = 0; j + 1 < k; j++) { int lca = dbl.lca(x[j], x[j + 1]); if(dbl.depth[lowest] > dbl.depth[lca]) lowest = lca; ans += dbl.fold(lca, x[j + 1], 0); } ans += dbl.fold(lowest, x[0], 0); cout << ans << "\n"; } return 0; }