#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <set>
using ll = long long;
#define debug(x) #x << " = " << x << '\n'
struct Fruit {
int d, w;
};
const int NMAX = 1e5;
const int DMAX = 1e5 + 7;
std::vector<int> g[NMAX + 1];
Fruit a[NMAX + 1];
std::set<int> timeStamps[NMAX + 1];
struct Segtree {
struct Node {
ll maxi;
ll lazyAdd;
ll lazySet;
Node* l;
Node* r;
Node() : maxi(0), lazyAdd(0), lazySet(0), l(nullptr), r(nullptr) {}
Node(ll x) : maxi(x), lazyAdd(0), lazySet(0), l(nullptr), r(nullptr) {}
void refresh() {
maxi = 0;
if (l != nullptr) {
maxi = std::max(maxi, l -> maxi);
}
if (r != nullptr) {
maxi = std::max(maxi, r -> maxi);
}
lazyAdd = lazySet = 0;
}
};
int n;
Node* root;
void init(int _n) {
n = _n + 2;
root = new Node();
}
void kill(Node* &root) {
if (root -> l != nullptr) {
kill(root -> l);
}
if (root -> r != nullptr) {
kill(root -> r);
}
delete(root);
}
void kill() {
kill(root);
}
void push(Node* &node, int tl, int tr) {
if (node == nullptr) {
node = new Node();
}
if (tl != tr) {
if (node -> l == nullptr) {
node -> l = new Node();
}
if (node -> r == nullptr) {
node -> r = new Node();
}
if (node -> lazySet != 0) {
node -> l -> lazySet = node -> lazySet;
node -> l -> lazyAdd = 0;
node -> r -> lazySet = node -> lazySet;
node -> r -> lazyAdd = 0;
}
node -> l -> lazyAdd += node -> lazyAdd;
node -> r -> lazyAdd += node -> lazyAdd;
}
if (node -> lazySet != 0) {
node -> maxi = node -> lazySet;
}
node -> maxi += node -> lazyAdd;
node -> lazySet = 0;
node -> lazyAdd = 0;
}
void rangeAdd(Node* &node, int tl, int tr, int l, int r, ll x) {
if (node == nullptr) {
node = new Node();
}
push(node, tl, tr);
if (l <= tl && tr <= r) {
node -> lazyAdd += x;
} else {
if (node -> l == nullptr) {
node -> l = new Node();
}
if (node -> r == nullptr) {
node -> r = new Node();
}
int mid = (tl + tr) / 2;
if (l <= mid) {
rangeAdd(node -> l, tl, mid, l, r, x);
}
if (mid < r) {
rangeAdd(node -> r, mid + 1, tr, l, r, x);
}
push(node -> l, tl, mid);
push(node -> r, mid + 1, tr);
node -> refresh();
// node -> maxi = std::max(node -> l -> maxi, node -> r -> maxi);
}
}
void rangeSet(Node* &node, int tl, int tr, int l, int r, ll x) {
if (node == nullptr) {
node = new Node();
}
push(node, tl, tr);
if (l <= tl && tr <= r) {
node -> lazySet = x;
} else {
if (node -> l == nullptr) {
node -> l = new Node();
}
if (node -> r == nullptr) {
node -> r = new Node();
}
int mid = (tl + tr) / 2;
if (l <= mid) {
rangeSet(node -> l, tl, mid, l, r, x);
}
if (mid < r) {
rangeSet(node -> r, mid + 1, tr, l, r, x);
}
push(node -> l, tl, mid);
push(node -> r, mid + 1, tr);
node -> refresh();
}
}
ll query(Node* &node, int tl, int tr, int p) {
if (node == nullptr) {
node = new Node();
}
push(node, tl, tr);
if (tl == tr) {
return node -> maxi;
} else {
int mid = (tl + tr) / 2;
if (p <= mid) {
if (node -> l == nullptr) {
node -> l = new Node();
}
return query(node -> l, tl, mid, p);
} else {
if (node -> r == nullptr) {
node -> r = new Node();
}
return query(node -> r, mid + 1, tr, p);
}
}
}
void rangeAdd(int l, int r, ll x) {
if (l > r) {
return;
}
rangeAdd(root, 0, n, l, r, x);
}
void rangeSet(int l, int r, ll x) {
if (l > r) {
return;
}
rangeSet(root, 0, n, l, r, x);
}
ll query(int p) {
return query(root, 0, n, p);
}
int findNextGr(Node* &node, int tl, int tr, ll x) {
if (node == nullptr) {
node = new Node();
}
push(node, tl, tr);
if (node -> maxi <= x) {
return -1;
}
if (tl == tr) {
return tl;
}
int mid = (tl + tr) / 2;
int aux = findNextGr(node -> l, tl, mid, x);
if (aux != -1) {
return aux;
}
return findNextGr(node -> r, mid + 1, tr, x);
}
int findNextGr(int p, ll x) {
int q = findNextGr(root, 0, n, x);
if (q == -1) {
return DMAX + 1;
}
return q;
}
ll queryMax() {
push(root, 0, n);
return root -> maxi;
}
};
// pun query pe u si dupa fac un max= da asta pare cam greu
// in schimb cealalta chestie ce face e asa:
// tin intervalele consecutive de valori egale
// fac += pe niste pozitii
Segtree DS[NMAX + 1];
void dfs(int u) {
int heavySon = 0;
for (const auto &v : g[u]) {
dfs(v);
if (heavySon == 0 || (int) timeStamps[v].size() > (int) timeStamps[heavySon].size()) {
heavySon = v;
}
}
if (heavySon) {
std::swap(timeStamps[u], timeStamps[heavySon]);
std::swap(DS[u], DS[heavySon]);
} else {
DS[u].init(DMAX + 1);
timeStamps[u].insert(0);
timeStamps[u].insert(DMAX + 1);
}
timeStamps[u].insert(a[u].d);
for (const auto &v : g[u]) {
if (v != heavySon) {
int tprev = 0;
ll vprev = 0;
for (int t : timeStamps[v]) {
DS[u].rangeAdd(tprev, t - 1, vprev);
vprev = DS[v].query(t);
tprev = t;
timeStamps[u].insert(t);
}
timeStamps[v].clear();
DS[v].kill();
}
}
if (a[u].d != 0) {
ll value = DS[u].query(a[u].d) + a[u].w;
int p = DS[u].findNextGr(a[u].d, value);
DS[u].rangeSet(a[u].d, p - 1, value);
}
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#endif
std::ios_base::sync_with_stdio(false);
std::cin.tie(0);
int n, m, k;
std::cin >> n >> m >> k;
for (int i = 2; i <= n; i++) {
int p;
std::cin >> p;
g[p].push_back(i);
}
for (int i = 1; i <= n; i++) {
a[i].d = a[i].w = 0;
}
for (int i = 0; i < m; i++) {
int u;
std::cin >> u;
std::cin >> a[u].d >> a[u].w;
}
dfs(1);
std::cout << DS[1].queryMax();
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |