原本写的 dfs,后面用的题解写的循环写法,但是没啥用,都是 WA
#include<bits/stdc++.h>
using namespace std;
const long long MAXN = 6e5+5;
struct edge{
long long nxt,to;
edge(){}
edge(long long _nxt,long long _to){
nxt = _nxt,to = _to;
}
}e[MAXN];
long long cnt,head[MAXN],dep[MAXN],die[MAXN],ans[MAXN],rt[MAXN],dist[MAXN],ls[MAXN],add[MAXN],times[MAXN],rs[MAXN],s[MAXN],c[MAXN],h[MAXN],a[MAXN],fa[MAXN],v[MAXN];
void pushdown(long long now){
if(ls[now]){
times[ls[now]] *= times[now];
add[ls[now]]*=times[now];
add[ls[now]]+=add[now];
s[ls[now]]*=times[now]; //因为 add 已经乘过了,所以如果先加再乘那么就会多乘一次
s[ls[now]]+=add[now];
}
if(rs[now]){
times[rs[now]] *= times[now];
add[rs[now]]*=times[now];
add[rs[now]]+=add[now];
s[rs[now]]*=times[now];
s[rs[now]]+=add[now];
}
times[now] = 1;
add[now] = 0;
}
long long merge(long long x,long long y){
if(!x || !y) return x + y;
pushdown(x);pushdown(y);
if(s[x] > s[y]) swap(x,y); //维护一个小根堆
rs[x] = merge(rs[x],y); //左偏,所以这样可以尽可能平均
if(dist[ls[x]] < dist[rs[x]]) swap(ls[x],rs[x]);
dist[x] = dist[rs[x]] + 1;
return x;
}
void add_edge(long long from,long long to){
e[++cnt] = edge(head[from],to);
head[from] = cnt;
}
int main(){
long long n,m;
cin>>n>>m;
for(long long i=1; i<=n; i++){
cin>>h[i];
rt[i] = -1;
}
dep[1] = 1;dist[0] = -1; //一定要记得 dep[1] = 1,不要 dep[1]=0,因为如果只是打过了 1 也算是占领一座
for(long long i=2; i<=n; i++){
cin>>fa[i]>>a[i]>>v[i];
dep[i] = dep[fa[i]] + 1;
}
for(long long i=1; i<=m; i++){
times[i] = 1;
cin>>s[i]>>c[i];
if(rt[c[i]] == -1) rt[c[i]] = i;
else rt[c[i]] = merge(rt[c[i]],i);
}
for(int i=n; i>=1; i--){ //根据题目性质
while(rt[i]!=-1){
if(h[i] > s[rt[i]]){
die[rt[i]] = i;
pushdown(rt[i]);
if(!ls[rt[i]]) rt[i] = -1;
else rt[i] = merge(ls[rt[i]],rs[rt[i]]);
}
else
break;
}
if(i == 1) break;
if(rt[i] == -1) continue;
if(a[i] == 1){
s[rt[i]]*=v[i];add[rt[i]]*=v[i];times[rt[i]]*=v[i];
}
else{
add[rt[i]]+=v[i];s[rt[i]]+=v[i];
}
pushdown(rt[i]);
if(rt[fa[i]] == -1) rt[fa[i]] = rt[i];
else rt[fa[i]] = merge(rt[fa[i]],rt[i]);
}
for(long long i=1; i<=m; i++){
ans[die[i]]++;
}
for(long long i=1; i<=n; i++){
printf("%lld\n",ans[i]);
}
for(long long i=1; i<=m; i++){
printf("%lld\n",dep[c[i]] - dep[die[i]]);
}
return 0;
}