分析:
明显城市管辖图是一棵树,设这棵树的最大深度是 deep,暴力做法是对于每个骑士分别统计,则这样复杂度就是 O ( m ∗ d e e p ) O(m*deep) O(m∗deep) 1 < = d e e p < = n 1<=deep<=n 1<=deep<=n肯定会T,我们考虑对每个城市维护一个骑士战斗力的小顶堆,不断弹出堆顶元素直到 堆顶战斗力>=防御值, 则堆中剩下的骑士又可以往上继续攻击,统计更新。因为有堆的合并,所以用左偏树,然后节点偏大,所以标记一下(即线段树的lazy数组)
代码:
#include<bits/stdc++.h>
using namespace std;
#define I inline
#define rg register
#define N 300000+10
#define LL long long
#define rep(i,a,b) for(rg int i=a;i<=b;i++)
const int BUF_SIZE = 1 << 22;
char rr[BUF_SIZE], *csy1, *csy2;
#define GC \
(csy1 == csy2 && (csy2 = (csy1 = rr) + fread(rr, 1, BUF_SIZE, stdin), csy1 == csy2) ? EOF : *csy1++)
I LL rd()
{
LL x=0,f=0;char c=GC;
while(!isdigit(c)){f|=c=='-';c=GC;}
while( isdigit(c)){x=(x<<3)+(x<<1)+(c-48);c=GC;}
return f?-x:x;
}
LL h[N],a[N],v[N];
LL s[N],lazy_mul[N],lazy_add[N];
int L[N],R[N],dis[N];
int ans1[N],ans2[N],dep[N],rt[N],c[N];
int n,m;
void cal(int u,LL mul,LL add)
{
if(!u) return;
s[u]*=mul,s[u]+=add;
lazy_mul[u]*=mul,lazy_add[u]*=mul,lazy_add[u]+=add;
}
void pushdown(int u)
{
cal(L[u],lazy_mul[u],lazy_add[u]);
cal(R[u],lazy_mul[u],lazy_add[u]);
lazy_mul[u]=1,lazy_add[u]=0;
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
pushdown(x);
pushdown(y);
if(s[x]>s[y]) swap(x,y);
R[x]=merge(y,R[x]);
if(dis[L[x]]<dis[R[x]]) swap(L[x],R[x]);
dis[x]=dis[R[x]]+1;
return x;
}
int pop(int u)
{
return merge(R[u],L[u]);
}
struct node{
int to,nxt;
}e[N];
int head[N],tot=1;
void addedge(int u,int v)
{
e[++tot]=(node){v,head[u]};
head[u]=tot;
}
void dfs(int u)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
dep[v]=dep[u]+1;
dfs(v);
rt[u]=merge(rt[u],rt[v]);
}
while(rt[u]&&s[rt[u]]<h[u])
{
pushdown(rt[u]);
ans1[u]++;
ans2[rt[u]]=dep[c[rt[u]]]-dep[u];
rt[u]=pop(rt[u]);
}
if(u==1)
{
while(rt[u])
{
pushdown(rt[u]);
ans2[rt[u]]=dep[c[rt[u]]]+1;
rt[u]=pop(rt[u]);
}
return;
}
if(a[u]) cal(rt[u],v[u],0);
else cal(rt[u],1,v[u]);
}
int main()
{
n=rd(),m=rd();
rep(i,1,n) h[i]=rd();
rep(i,2,n)
{
LL f=rd(); a[i]=rd(),v[i]=rd();
addedge(f,i);
}
rep(i,1,m)
{
s[i]=rd(),c[i]=rd();
lazy_mul[i]=1;
rt[c[i]]=merge(rt[c[i]],i);
}
dfs(1);
rep(i,1,n) printf("%d\n",ans1[i]);
rep(i,1,m) printf("%d\n",ans2[i]);
}