题目描述:
雾.
题目分析:
改变操作乘法是没有负数的,那么就不会改变大小关系,我们就可以DFS树,然后用可合并堆进行操作。
Splay+启发式合并也可以过
题目链接:
Ac 代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
const int maxm=310000;
struct left_tree{
int adi,adx;
int dis,ls,rs,fa;
int v;
}st[maxm];
int begin[maxm],end[maxm],dead[maxm],deep[maxm];
int rt[maxm];
int flag[maxm],v[maxm],d[maxm];
int n,m;
int head[maxm],net[maxm],to[maxm],cnt;
inline void addedge(int u,int v)
{
cnt++;
to[cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
inline void col(int o,int addi,int addx)
{
if(!o) return;
//printf("-1:%d-\n",st[o].v);
st[o].v*=addx;
//printf("-2:%d-\n",st[o].v);
st[o].v+=addi;
//printf("-3:%d-\n",st[o].v);
st[o].adi*=addx,st[o].adx*=addx;
st[o].adi+=addi;
}
inline void pushdown(int o)
{
col(st[o].ls,st[o].adi,st[o].adx);
col(st[o].rs,st[o].adi,st[o].adx);
st[o].adi=0,st[o].adx=1;
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
pushdown(x),pushdown(y);
if(st[x].v>st[y].v||(st[x].v==st[y].v&&x>y))
std::swap(x,y);
st[x].rs=merge(st[x].rs,y);
st[st[x].rs].fa=x;
if(st[st[x].ls].dis<st[st[x].rs].dis) std::swap(st[x].ls,st[x].rs);
st[x].dis=st[st[x].rs].dis+1;
return x;
}
inline int pop(int o)
{
return merge(st[o].ls,st[o].rs);
}
void dfs(int now,int fa)
{
deep[now]=deep[fa]+1;
for(int i=head[now];i;i=net[i])
if(to[i]!=fa)
dfs(to[i],now);
for(int i=head[now];i;i=net[i])
if(to[i]!=fa)
rt[now]=merge(rt[now],rt[to[i]]);
//printf("%d %d %d\n",now,st[rt[now]].v,d[now]);
while(rt[now]&&st[rt[now]].v<d[now])
{
pushdown(rt[now]);
dead[now]++;
end[rt[now]]=now;
rt[now]=pop(rt[now]);
}
if(!flag[now]) col(rt[now],v[now],1);
else col(rt[now],0,v[now]);
}
main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&d[i]);
for(int i=2;i<=n;i++)
{
int fax;
scanf("%lld%lld%lld",&fax,&flag[i],&v[i]);
addedge(fax,i);
}
for(int i=1;i<=m;i++) st[i].adi=0,st[i].adx=1;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld",&st[i].v,&begin[i]);
rt[begin[i]]=merge(rt[begin[i]],i);
}
//for(int i=1;i<=n;i++) printf("%d\n",st[rt[i]].v);
dfs(1,0);
for(int i=1;i<=n;i++) printf("%lld\n",dead[i]);
for(int i=1;i<=m;i++) printf("%lld\n",deep[begin[i]]-deep[end[i]]);
return 0;
}