トピックリンク:ポイント私はああ╭(╯^╰)╮
効果の件名:
の点の根
ツリーは、各ポイントは、貴重なリンゴの愛
の木を持っています
モニター:
地点で
、モニタを有し、それは最短距離で検出することができます
サブツリー内のすべてのポイントを
監視する必要の破壊
最大の収穫を求めて
問題解決のアイデア:
次の点を説明します。
各モニタについて、最適な戦略は貪欲の遠い点受け入れるべきトラフィックである
に挿入される短い長鎖チェーン上の各マージ息子の
長鎖上の各点に一度挿入され、時間複雑さ:
各チェーン上の位置で長鎖の中に挿入され、時間の複雑:
コア:最小カットモデリング、長鎖分割の最適化は、合併しました
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
#define fi first
#define se second
using namespace std;
typedef long long ll;
using pii = pair <int,ll>;
const int maxn = 3e5 + 5;
int T, n, m, f[maxn], a[maxn], dep[maxn];
vector <pii> cam[maxn];
map <int, ll> mp[maxn];
void merge(auto &mp1, auto &mp2){
if(mp1.size() < mp2.size())
mp1.swap(mp2);
for(auto t : mp2) mp1[t.fi] += t.se;
}
int main() {
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) mp[i].clear(), cam[i].clear();
for(int i=2, x; i<=n; i++){
scanf("%d", &x);
f[i] = x;
dep[i] = dep[x] + 1;
}
ll ans = 0;
for(int i=1; i<=n; i++) scanf("%d", a+i), ans += a[i];
for(int i=1; i<=m; i++){
int x, k, c;
scanf("%d%d%d", &x, &k, &c);
cam[x].push_back({k, c});
}
for(int i=n; i; i--){
mp[i][-dep[i]] += a[i];
for(auto &u : cam[i]){
auto it = mp[i].lower_bound(-dep[i] - u.fi);
while(it != mp[i].end()) {
if(it->se <= u.se){
ans -= it->se;
u.se -= it->se;
it = mp[i].erase(it); // 下一个
} else {
ans -= u.se;
it->se -= u.se;
u.se = 0;
break;
}
}
}
if(f[i]) merge(mp[f[i]], mp[i]);
}
printf("%lld\n", ans);
}
}