RT,问题见代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cassert>
#define N 300050
#define LL long long
using namespace std;
int ans1[N],ans2[N],c[N];
int n,m,fa[N],dep[N],die[N],a[N];
LL def[N],v[N],add[N],mul[N],s[N];
inline int qr()
{
char a=0;int w=1,x=0;
while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
return x*w;
}
inline LL qrl()
{
char a=0;LL w=1,x=0;
while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
return x*w;
}
int rt[N],l[N],r[N],dis[N];
inline void spread(int p)//在左偏树上下传标记
{
if(!add[p]&&mul[p]==1) return ;
if(l[p])
{
mul[l[p]]*=mul[p];
add[l[p]]*=mul[p];
add[l[p]]+=add[p];
s[l[p]]*=mul[p];
s[l[p]]+=add[p];
}
if(r[p])
{
mul[r[p]]*=mul[p];
add[r[p]]*=mul[p];
add[r[p]]+=add[p];
s[r[p]]*=mul[p];
s[r[p]]+=add[p];
}
add[p]=0,mul[p]=1;
}
inline int merge(int x,int y)
{
if(!x||!y) return x|y;
spread(x); spread(y);
if(s[x]>s[y]) swap(x,y);
r[x]=merge(r[x],y);
if(dis[r[x]]>dis[l[x]]) swap(l[x],r[x]);
dis[x]=dis[r[x]]+1;
return x;
}
int main()
{
n=qr();m=qr();
for(register int i=1;i<=n;i++) rt[i]=-1;
for(register int i=1;i<=n;i++) def[i]=qrl();
dep[1]=1;
//**************************************************************//问题在这里
dis[0]=-1; //这里左偏树节点零为负数时就能过 其余几乎全WA 这是为什么?
//**************************************************************//
for(register int i=2;i<=n;i++)
{
fa[i]=qr();a[i]=qr();v[i]=qrl();
dep[i]=dep[fa[i]]+1;
}
for(register int i=1;i<=m;i++)
{
mul[i]=1;
s[i]=qrl();c[i]=qr();
if(rt[c[i]]==-1) rt[c[i]]=i;
else rt[c[i]]=merge(rt[c[i]],i);
}
for(register int i=n;i>=1;i--)//从叶子到根遍历树
{
while(rt[i]!=-1)//这个节点上有骑士
if(s[rt[i]]<def[i])//骑士打不过
{
die[rt[i]]=i;//骑士挂在这个节点上
spread(rt[i]);
if(!l[rt[i]]) rt[i]=-1;//如果这棵树空了,标记一下
else rt[i]=merge(l[rt[i]],r[rt[i]]);//把根节点删了
}
else break;
if(i==1) break;
if(rt[i]==-1) continue;
if(a[i]) mul[rt[i]]*=v[i],add[rt[i]]*=v[i],s[rt[i]]*=v[i];//改变根节点
else add[rt[i]]+=v[i],s[rt[i]]+=v[i];
spread(rt[i]);//根节点标记下传
if(rt[fa[i]]==-1) rt[fa[i]]=rt[i];//如果父节点没东西直接换下根
else rt[fa[i]]=merge(rt[fa[i]],rt[i]);//有的话合并
}
for(register int i=1;i<=m;i++) ans1[die[i]]++;
for(register int i=1;i<=m;i++) ans2[i]=dep[c[i]]-dep[die[i]];
for(register int i=1;i<=n;i++) printf("%d\n",ans1[i]);
for(register int i=1;i<=m;i++) printf("%d\n",ans2[i]);
return 0;
}