对于每个点维护一颗左偏树,最开始这棵树只包含从这个点出发的人。
可以按拓扑序枚举,枚举到一个点,把它的左偏树和所有儿子的左偏树合并(因为是左偏树,所以合并复杂度是logn),把战斗力小的弹出。
至于修改打两个标记就好了。
#include <cstdio>
#define N 300010
typedef long long ll;
struct tree{
ll taga,tagb,w;
int d,l,r,g;
}T[N];
struct edge{
int t,nx;
}E[N<<1];
int n,m,u,x,cnt,t;
int G[N],dsl[N],dpt[N],Root[N],f[N];
ll A[N],B[N],C[N],Ans1[N],Ans2[N];
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
if(p1==p2){
p2=(p1=buf)+fread(buf,1,100000,stdin);
if(p1==p2) return EOF;
}
return *p1++;
}
inline void reaD(int &x){
char Ch=gc();x=0;int f=1;
for(;Ch>'9'||Ch<'0';Ch=gc())if(Ch=='-')f=-1;
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=gc());x*=f;
}
inline void reaD(ll &x){
char Ch=gc();x=0;int f=1;
for(;Ch>'9'||Ch<'0';Ch=gc())if(Ch=='-')f=-1;
for(;Ch>='0'&&Ch<='9';x=x*10+Ch-'0',Ch=gc());x*=f;
}
inline void InserT(int x,int y){
E[++cnt].t=y;E[cnt].nx=G[x];G[x]=cnt;
}
inline int newd(int x,int g){
T[++cnt].w=x;T[cnt].g=g;
T[cnt].taga=1;T[cnt].tagb=0;
return cnt;
}
inline void swap(int &x,int &y){
int z=x;x=y;y=z;
}
inline void liflag(int x,ll a,ll b){
if(a) T[x].taga*=a,T[x].tagb*=a;
if(b) T[x].tagb+=b;
}
inline void pushdown(int x){
if(T[x].taga>1){
T[x].w*=T[x].taga;
liflag(T[x].l,T[x].taga,0);
liflag(T[x].r,T[x].taga,0);
T[x].taga=1;
}
if(T[x].tagb){
T[x].w+=T[x].tagb;
liflag(T[x].l,0,T[x].tagb);
liflag(T[x].r,0,T[x].tagb);
T[x].tagb=0;
}
}
int merge(int x,int y){
if(x==0||y==0) return x+y;
pushdown(x);pushdown(y);
if(T[x].w>T[y].w) swap(x,y);
T[x].r=merge(T[x].r,y);
if(T[T[x].r].d>T[T[x].l].d) swap(T[x].l,T[x].r);
if(T[x].r==0) T[x].d=0; else T[x].d=T[T[x].r].d+1;
return x;
}
void dfs(int x){
dsl[++t]=x;
for(int i=G[x];i;i=E[i].nx){
dpt[E[i].t]=dpt[x]+1;
dfs(E[i].t);
}
}
inline ll top(int x){
pushdown(x);
return T[x].w;
}
inline int pop(int x){
pushdown(x);
return merge(T[x].l,T[x].r);
}
int w[30],wt;
inline void Pt(ll x){
if(!x){putchar(48);putchar('\n');return;}
while(x)w[++wt]=x%10,x/=10;
for(;wt;wt--)putchar(48+w[wt]);putchar('\n');
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
reaD(n);reaD(m);
for(int i=1;i<=n;i++) reaD(A[i]);
for(int i=2;i<=n;i++) reaD(u),reaD(B[i]),reaD(C[i]),InserT(u,i);
cnt=0;
for(int i=1;i<=m;i++){
reaD(x);reaD(f[i]);
Root[f[i]]=merge(Root[f[i]],newd(x,i));
}
dfs(1);
for(int k=t;k;k--){
int x=dsl[k];
for(int i=G[x];i;i=E[i].nx) Root[x]=merge(Root[x],Root[E[i].t]);
while(Root[x]!=0&&top(Root[x])<A[x]){
Ans2[T[Root[x]].g]=dpt[f[T[Root[x]].g]]-dpt[x];
Root[x]=pop(Root[x]),Ans1[x]++;
}
if(B[x]) liflag(Root[x],C[x],0);
else liflag(Root[x],0,C[x]);
}
while(Root[1]!=0){
Ans2[T[Root[1]].g]=dpt[f[T[Root[1]].g]]+1;
Root[1]=pop(Root[1]);
}
for(int i=1;i<=n;i++) Pt(Ans1[i]);
for(int i=1;i<=m;i++) Pt(Ans2[i]);
}