Submission #198118

#TimeUsernameProblemLanguageResultExecution timeMemory
198118model_codeMagic Tree (CEOI19_magictree)C++17
100 / 100
503 ms110312 KiB
// Stack of interval trees over implicit HLD. // O(N log^2 N) #include <bits/stdc++.h> using namespace std; using wgt = unsigned long long; class Solver { using day = int; class IntervalTree { struct node { wgt val, add; }; int b; vector<node> T; inline __attribute__((always_inline)) void upd(int i, bool leaf) { wgt add = T[i].add; if(add == 0) return; T[i].add = 0; T[i].val += add; if(!leaf) { T[2*i].add += add; T[2*i+1].add += add; } } void traverse_add_internal(vector< pair<int, wgt> > & L_values, int & pos, wgt & cur_max, int i, int n_l, int n_r) { if(n_l+1 == n_r) { T[i].val = cur_max = max(cur_max, T[i].val + T[i].add); T[i].add = 0; if(pos+1 != (int)L_values.size() && L_values[pos+1].first == n_l) pos++; T[i].val += L_values[pos].second; return; } if(L_values[pos].first < n_l && (pos+1 == (int)L_values.size() || n_r <= L_values[pos+1].first)) { cur_max = max(cur_max, T[i].val + T[i].add); T[i].add += L_values[pos].second; upd(i, n_l+1 == n_r); return; } upd(i, n_l+1 == n_r); int c = (n_l + n_r) / 2; traverse_add_internal(L_values, pos, cur_max, 2*i, n_l, c); traverse_add_internal(L_values, pos, cur_max, 2*i+1, c, n_r); T[i].val = max(T[2*i].val, T[2*i+1].val); } public: IntervalTree() {} IntervalTree(int N) { b = 1; while(b < N) b *= 2; T.resize(2*b+1, {0, 0}); } void add(int l, int r, wgt w_add, int i = 1, int n_l = 0, int n_r = 0) { if(i == 1) n_r = b; if(n_l == l && n_r == r) { T[i].add += w_add; upd(i, n_l+1 == n_r); return; } upd(i, n_l+1 == n_r); if(n_l >= r || l >= n_r) return; int c = (n_l + n_r) / 2; add(l, min(r, c), w_add, 2*i, n_l, c); add(max(l, c), r, w_add, 2*i+1, c, n_r); T[i].val = max(T[2*i].val, T[2*i+1].val); } void put(int pos, wgt w) { int cur = 1, n_l = 0, n_r = b; while(n_l+1 != n_r) { upd(cur, false); int c = (n_l + n_r) / 2; if(pos < c) { upd(2*cur+1, c+1 == n_r); cur = 2*cur; n_r = c; } else { upd(2*cur, n_l+1 == c); cur = 2*cur+1; n_l = c; } } T[cur].val = w; T[cur].add = 0; for(cur /= 2; cur > 0; cur /= 2) T[cur].val = max(T[2*cur].val, T[2*cur+1].val); } wgt get_max(int pos) { // max [0..pos] wgt ret = 0; int cur = 1, n_l = 0, n_r = b; while(true) { upd(cur, n_l+1 == n_r); if(pos+1 == n_r) { ret = max(ret, T[cur].val); break; } if(T[cur].val <= ret) break; int c = (n_l + n_r) / 2; if(pos < c) { cur = 2*cur; n_r = c; continue; } upd(2*cur, n_l+1 == c); ret = max(ret, T[2*cur].val); cur = 2*cur+1; n_l = c; } return ret; } void traverse_add(vector< pair<int, wgt> > & L_values) { int pos = 0; wgt cur_max = 0; traverse_add_internal(L_values, pos, cur_max, 1, 0, b); } void traverse_extract_clear(vector< pair<int, wgt> > & L_values, wgt add = 0, int i = 1, int n_l = 0, int n_r = 0) { if(i == 1) n_r = b; add += T[i].add; T[i].add = 0; if(T[i].val == 0 || n_l+1 == n_r) { if(add+T[i].val > 0) if(L_values.empty() || L_values.back().second < add+T[i].val) L_values.push_back({n_l, add+T[i].val}); T[i].val = 0; return; } T[i].val = 0; int c = (n_l + n_r) / 2; traverse_extract_clear(L_values, add, 2*i, n_l, c); traverse_extract_clear(L_values, add, 2*i+1, c, n_r); } }; int N, K; vector< vector<int> > son; vector<wgt> W; vector<day> D; vector<int> sz, max_son; vector<wgt> LIS_W; // largest increasing subgraph weight vector<IntervalTree> interval_trees; int tree_stack_depth; void DFS_init(int R) { int max_son_sz = 0; for(auto v : son[R]) { DFS_init(v); sz[R] += sz[v]; if(sz[v] > max_son_sz) { max_son_sz = sz[v]; max_son[R] = v; } } } void DFS_solve(int R, IntervalTree & this_itree) { if(max_son[R] == 0) { if(D[R] > 0) { LIS_W[R] = W[R]; this_itree.put(D[R]-1, W[R]); } return; } DFS_solve(max_son[R], this_itree); for(auto v : son[R]) if(v != max_son[R]) { IntervalTree & subtree_itree = interval_trees[tree_stack_depth]; tree_stack_depth++; DFS_solve(v, subtree_itree); vector< pair<int, wgt> > subtree_L_values; subtree_L_values.reserve(sz[v]+1); subtree_itree.traverse_extract_clear(subtree_L_values); tree_stack_depth--; if(subtree_L_values.empty()) continue; if(subtree_L_values[0].first > 0) subtree_L_values.insert(begin(subtree_L_values), {0, 0}); this_itree.traverse_add(subtree_L_values); } if(D[R] > 0) { LIS_W[R] = this_itree.get_max(D[R]-1) + W[R]; this_itree.put(D[R]-1, LIS_W[R]); } } public: Solver(vector< vector<int> > & son_, vector<wgt> & W_, vector<day> & D_, int K_) : N(son_.size()), W(W_), K(K_), son(son_), D(D_) { // D[v] == 0: v is empty sz.resize(N, 1); max_son.resize(N, 0); // 0: leaf LIS_W.resize(N, 0); interval_trees.resize(18, IntervalTree(K)); tree_stack_depth = 0; DFS_init(0); } wgt solve() { IntervalTree & full_itree = interval_trees[tree_stack_depth]; tree_stack_depth++; DFS_solve(0, full_itree); wgt ans = full_itree.get_max(K-1); vector< pair<int, wgt> > V; full_itree.traverse_extract_clear(V); tree_stack_depth--; return ans; } }; int main() { cin.sync_with_stdio(0); cin.tie(0); int N, M, K; cin >> N >> M >> K; vector<int> par(N, 0); vector< vector<int> > son(N); for(int i = 1; i < N; i++) { cin >> par[i]; par[i]--; son[par[i]].push_back(i); } vector<wgt> W(N, 0); vector<int> D(N, 0); for(int i = 0; i < M; i++) { int v, d, w; cin >> v >> d >> w; v--; D[v] = d; W[v] = w; } Solver solver(son, W, D, K); cout << solver.solve() << "\n"; }

Compilation message (stderr)

magictree.cpp: In constructor 'Solver::Solver(std::vector<std::vector<int> >&, std::vector<long long unsigned int>&, std::vector<int>&, int)':
magictree.cpp:147:17: warning: 'Solver::W' will be initialized after [-Wreorder]
     vector<wgt> W;
                 ^
magictree.cpp:145:12: warning:   'int Solver::K' [-Wreorder]
     int N, K;
            ^
magictree.cpp:200:5: warning:   when initialized here [-Wreorder]
     Solver(vector< vector<int> > & son_, vector<wgt> & W_, vector<day> & D_, int K_)
     ^~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...