Submission #198117

#TimeUsernameProblemLanguageResultExecution timeMemory
198117model_codeMagic Tree (CEOI19_magictree)C++17
100 / 100
958 ms53052 KiB
// Compressed Fenwick trees over implicit HLD. Compression done using map<>.
// 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 l, r;
        };        

        vector<node> T;

        void upd(int i) {
            node & n = T[i];
            n.val += n.add;
            if(n.l+1 < n.r) {
                T[2*i].add += n.add;
                T[2*i+1].add += n.add;
            }
            n.add = 0;
        }

    public:
        IntervalTree() {}

        IntervalTree(int N) {
            int b = 1;
            while(b < N) b *= 2;
            T.reserve(2*b+1);
            T.resize(2, {0, 0, 0, b});
            for(int i = 1; ; i++) {
                if(i == (int)T.size() || T[i].l+1 == T[i].r) break;
                T.push_back({0, 0, T[i].l, (T[i].l+T[i].r)/2});
                T.push_back({0, 0, (T[i].l+T[i].r)/2, T[i].r});
            }
        }

        void add(int l, int r, wgt w_add, int i = 1) {
            node & n = T[i];
            if(n.l == l && n.r == r) {
                n.add += w_add;
                upd(i);
                return;
            }
            else if(n.add) upd(i);
            if(n.l >= r || l >= n.r) return;
            int c = (n.l + n.r) / 2;
            if(n.l+1 < n.r) {
                add(l, min(r, c), w_add, 2*i);
                add(max(l, c), r, w_add, 2*i+1);
                n.val = max(T[2*i].val, T[2*i+1].val);
            }
        }

        void put(int pos, wgt w, int i = 1) {
            node & n = T[i];
            if(n.l == pos && n.r == pos+1) {
                T[i].val = w;
                T[i].add = 0;
                return;
            }
            else if(n.add) upd(i);
            if(n.l > pos || pos >= n.r) return;
            put(pos, w, 2*i);
            put(pos, w, 2*i+1);
            n.val = max(T[2*i].val, T[2*i+1].val);
        }

        wgt get_max(int pos, int i = 1) { // max [l..r)
            node & n = T[i];
            if(n.add) upd(i);
            if(pos < n.l) return 0;
            if(n.r == pos+1) return n.val;
            int c = (n.l + n.r) / 2;
            wgt best_lft = get_max(min(pos, c-1), 2*i);
            if(pos < c) return best_lft;
            wgt best_rt  = get_max(pos, 2*i+1);
            return max(best_lft, best_rt);
        }
    };

    int N;
    vector< vector<int> > son;
    vector<wgt> W;
    vector<day> D;
    vector<int> sz, max_son;
    vector<wgt> LIS_W; // largest increasing subgraph weight

    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 compress(int R, map<day, int> & this_map, bool top = true) {
        if(D[R]) this_map[D[R]-1] = 0;
        for(auto v : son[R]) compress(v, this_map, false);
        if(top) {
            int n = 0;
            for(auto & p : this_map) p.second = n++;
        }
    }

    void DFS_solve(int R, map<day, int> & this_map, IntervalTree & this_ftree) {
        if(max_son[R] == 0) {
            if(D[R] > 0) {
                LIS_W[R] = W[R];
                this_ftree.put(this_map[D[R]-1], W[R]);
            }
            return;
        }

        DFS_solve(max_son[R], this_map, this_ftree);

        for(auto v : son[R]) if(v != max_son[R]) {
            map<int, int> subtree_D_map;
            compress(v, subtree_D_map);
            int m = subtree_D_map.size();

            IntervalTree subtree_ftree(m);

            DFS_solve(v, subtree_D_map, subtree_ftree);

            for(auto it = rbegin(subtree_D_map); it != rend(subtree_D_map); it++) {
                // keys in this_map are a superset of keys for subtree_D_map
                int this_compr_id = this_map[it->first];
                int subtree_compr_id = it->second;
                int this_compr_id_nxt;
                if(it == rbegin(subtree_D_map)) this_compr_id_nxt = this_map.size();
                else {
                    auto jt = it;
                    jt--;
                    this_compr_id_nxt = this_map[jt->first];
                }
                wgt orig_value = this_ftree.get_max(this_compr_id);
                wgt subtree_incr = subtree_ftree.get_max(subtree_compr_id);
                this_ftree.put(this_compr_id, orig_value);
                this_ftree.add(this_compr_id, this_compr_id_nxt, subtree_incr);
            }
        }

        if(D[R] > 0) {
            int this_compr_id = this_map[D[R]-1];
            LIS_W[R] = this_ftree.get_max(this_compr_id) + W[R];
            this_ftree.put(this_compr_id, LIS_W[R]);
        }
    }

public:
    Solver(vector< vector<int> > & son_, vector<wgt> & W_, vector<day> & D_) : N(son_.size()), son(son_), W(W_), D(D_) {
        // D[v] == 0: v is empty
        sz.resize(N, 1);
        max_son.resize(N, 0); // 0: leaf
        LIS_W.resize(N, 0);

        DFS_init(0);
    }

    wgt solve() {
        map<day, int> full_D_map;
        compress(0, full_D_map);
        int m = full_D_map.size();
        IntervalTree full_ftree(m);

        DFS_solve(0, full_D_map, full_ftree);

        return full_ftree.get_max(m-1);
    }
};

int main() {
    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);
    cout << solver.solve() << "\n";
}
#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...