题解:
带标记可并堆
用可并堆维护可以到某个城池的士兵
维护小根堆
堆顶小于h时就弹出来计算
注意什么时候下放!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=300009;
typedef long long Lint;
int n,m;
int s[maxn];
long long h[maxn];
int fa[maxn]={0},ch[maxn][2]={0},dis[maxn]={0};
long long ky[maxn],tag[maxn],mul[maxn];
void Putmul(int x,Lint y){
ky[x]=ky[x]*y;
tag[x]=tag[x]*y;
mul[x]=mul[x]*y;
}
void Puttag(int x,Lint y){
ky[x]=ky[x]+y;
tag[x]=tag[x]+y;
}
void pushdown(int x){
if(mul[x]!=1){
if(ch[x][0]){
Putmul(ch[x][0],mul[x]);
}
if(ch[x][1]){
Putmul(ch[x][1],mul[x]);
}
mul[x]=1;
}
if(tag[x]!=0){
if(ch[x][0]){
Puttag(ch[x][0],tag[x]);
}
if(ch[x][1]){
Puttag(ch[x][1],tag[x]);
}
tag[x]=0;
}
}
int Getf(int x){
while(fa[x])x=fa[x];
return x;
}
int Mer(int x,int y){
// pushdown(x);pushdown(y);
if((x==0)||(y==0))return x+y;
if(ky[x]>ky[y])swap(x,y);
pushdown(x);pushdown(y);
ch[x][1]=Mer(ch[x][1],y);
fa[ch[x][1]]=x;
if(dis[ch[x][1]]>dis[ch[x][0]])swap(ch[x][0],ch[x][1]);
dis[x]=dis[ch[x][1]]+1;
return x;
}
int rt[maxn]={0};
int cntedge=0;
int head[maxn]={0};
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
}
int opty[maxn];
long long v[maxn];
int att[maxn],def[maxn]={0};
int dep[maxn]={0};
void Dp(int x,int father){
dep[x]=dep[father]+1;
for(int i=head[x];i;i=nex[i]){
Dp(to[i],x);
pushdown(rt[x]);pushdown(rt[to[i]]);
rt[x]=Mer(rt[x],rt[to[i]]);
}
while((rt[x])&&(ky[rt[x]]<h[x])){
int y=rt[x];
att[y]=dep[s[y]]-dep[x];
def[x]++;
fa[ch[y][0]]=0;
fa[ch[y][1]]=0;
pushdown(y);
rt[x]=Mer(ch[y][0],ch[y][1]);
}
if(opty[x]==0){
Puttag(rt[x],v[x]);
}else{
Putmul(rt[x],v[x]);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&h[i]);
for(int i=2;i<=n;++i){
int x;scanf("%d",&x);Addedge(x,i);
scanf("%d%lld",&opty[i],&v[i]);
}
for(int i=1;i<=m;++i){
scanf("%lld%d",&ky[i],&s[i]);
mul[i]=1;
rt[s[i]]=Mer(rt[s[i]],i);
}
Dp(1,0);
while(rt[1]){
int x=rt[1];
att[x]=dep[s[x]];
fa[ch[x][0]]=0;
fa[ch[x][1]]=0;
rt[1]=Mer(ch[x][0],ch[x][1]);
}
for(int i=1;i<=n;++i){
printf("%d
",def[i]);
}
for(int i=1;i<=m;++i){
printf("%d
",att[i]);
}
return 0;
}