제출 #418706

#제출 시각아이디문제언어결과실행 시간메모리
418706gmyuMagic Tree (CEOI19_magictree)C++14
100 / 100
178 ms36876 KiB
/*
ID: USACO_template
LANG: C++
PROG: 10542-005137
*/
#include <iostream>  //cin , cout
#include <fstream>   //fin, fout
#include <stdio.h>   // scanf , pringf
#include <cstdio>
#include <algorithm> // sort , stuff
#include <stack>     // stacks
#include <queue>     // queues
#include <map>
#include <string>
#include <string.h>
#include <set>

using namespace std;

typedef pair<int, int>          pii;
typedef vector<int>             vi;     /// adjlist without weight
typedef vector<pii>             vii;    /// adjlist with weight
typedef vector<pair<int,pii>>   vpip;   /// edge with weight
typedef long long               ll;

#define mp  make_pair
#define ff  first
#define ss  second
#define pb  push_back
#define sz(x)   (int)(x).size()

const int MOD = 1e9+7;  // 998244353;
const int MX  = 2e5+5;   //
const ll  INF = 1e18;    //

#define MAXV 100007
#define MAXE 100007



bool debug;

int N, M, K;
vi adjlist[MAXV];
int d[MAXV], w[MAXV];
map<int, ll> dp[MAXV];
/** dp[v, t] is the max added fruit at node v at time t.
    for a fixed v, the dp[t] looks like a stair-case plot. At time t, increase by dp[t] amount
    for v, "sum up" all child nodes, using small to large merge
    the key is to deal with node v update when there is a fruit on v. Basically, we want to get the fruit as early as possible,
    any child with t < d[v], we can simply take it; for t > d[v], whatever on node v overtakes it until it can not overtake anymore
*/

void dfs(int v, int p=0) {
    if(sz(adjlist[v])==0) { // leaf
        if(d[v]!=0) dp[v][d[v]] = w[v];
        return;
    }

    for(auto x : adjlist[v]) {
        if(x == p) continue;
        dfs(x, v);

        // small to large merge, O(N log N)
        if(sz(dp[v])<sz(dp[x])) dp[v].swap(dp[x]);
        for(auto y : dp[x]) {
            if(y.ss == 0) continue;
            dp[v][y.ff] += y.ss;
        }
    }

    if(d[v]==0) return;   // no fruit here

    dp[v][d[v]] += w[v];    // now deal with insertion;
    int cur_d = d[v], cur_val = w[v];
    while(true) {
        auto it = dp[v].upper_bound(cur_d);
        if(it == dp[v].end()) break;
        if(cur_val >= it->ss) { // adder overtake this day's value
            cur_val -= it->ss;
            dp[v].erase(it);
        } else {
            it->ss -= cur_val;
            break;
        }
    }

    if(debug) {
        cout << v << " : after " << endl;
        for(auto x : dp[v]) cout << " " << x.ff << " - " << x.ss << endl;
    }

}

int main() {
    debug = false;
    ios_base::sync_with_stdio(false); cin.tie(0);

    cin >> N >> M >> K;
    for(int i=2; i<=N; i++) {
        int a; cin >> a;
        adjlist[a].pb(i);
    }
    for(int i=0;i<M;i++) {
        int a, b, c; cin >> a >> b >> c;
        d[a] = b; w[a] = c;
    }

    dfs(1);

    ll ans = 0LL;
    for(auto x : dp[1]) ans += x.ss;
    cout << ans << endl;

    if(debug) cout << endl << "EOL" << endl;

}

/**
6 4 10
1
2
1
4
4
3 4 5
4 7 2
5 4 1
6 9 3

4 3 3
1
2
2
2 2 50
3 3 10
4 4 10

*/
#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...