一开始只会傻傻地打暴力。
暴力打完想了想感觉可以用倍增乱搞一下。
那时候想的倍增无法修改武力值,于是感觉可以做ai=0,vi=0的点。
用倍增求出f[i][j]表示i点向上2^j步内所有节点上防御值的最大值
然后就可以用类似于二分的方法去求啦~
纯属口糊,打代码的时候都打错了,所以跳过这个方法啊,去看正解。
满分其实有两种方法。
一种就是倍增(我还没搞懂,下次补全)
还有一种就是可并堆。
一些骑士往上打汇集在一个点上,有些骑士是会在这个点上牺牲的,这个我们当然是用堆来实现。
但又要支持把下面所有儿子节点活下来的骑士都并到父亲节点上,所以用到了可并堆这个数据结构。
没想到应该是因为好久没用了吧。
至于打好一座城池之后,战斗力的变化,可以打标记。
应该挺好懂的吧~稍微写一点注释好了qwq
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define ll long long
#define N 300000+3000
using namespace std;
int n,m,cnt,vet[N+N],Next[N+N],head[N],ans1[N],ans2[N],dep[N],c[N],fa[N],opt[N];
ll v[N],h[N];
struct leo{
int l,r,rt,dist,key;
ll add,mul,val;
}heap[N+N];
inline void add_edge(int u,int v){
vet[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
inline void modify(int x,ll add1,ll add2){
heap[x].val=heap[x].val*add2+add1;
heap[x].add=heap[x].add*add2+add1;
heap[x].mul=heap[x].mul*add2;
}
inline void pushdown(int x){
if(heap[x].l) modify(heap[x].l,heap[x].add,heap[x].mul); //加标记
if(heap[x].r) modify(heap[x].r,heap[x].add,heap[x].mul); //乘标记
heap[x].add=0;heap[x].mul=1;
}
inline int merge(int x,int y){
if(!x) return y;
if(!y) return x;
if(heap[x].val>heap[y].val) swap(x,y);
pushdown(x);
heap[x].r=merge(heap[x].r,y);
if(heap[heap[x].r].dist>heap[heap[x].l].dist) swap(heap[x].l,heap[x].r);
heap[x].dist=heap[heap[x].r].dist+1;
return x;
}
void erase(int &x){
pushdown(x);
x=merge(heap[x].l,heap[x].r);
}
void dfs(int u){
for(int i=head[u];i;i=Next[i]){
int v=vet[i];
if(v==fa[u]) continue;
dep[v]=dep[u]+1;
dfs(v);
heap[u].rt=merge(heap[u].rt,heap[v].rt); //将儿子节点所有活下来的骑士都汇集到当前节点
}
while(heap[u].rt && heap[heap[u].rt].val<h[u]){
ans2[heap[u].rt]=u;
ans1[u]++;
erase(heap[u].rt);
} //看有几个骑士会牺牲
if(opt[u]==0) modify(heap[u].rt,v[u],1);
else modify(heap[u].rt,0,v[u]);
}
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++){
scanf("%d%d%lld",&fa[i],&opt[i],&v[i]);
add_edge(fa[i],i);add_edge(i,fa[i]);
}
for(int i=1;i<=m;i++){
scanf("%lld%d",&heap[i].val,&c[i]);
heap[i].mul=1;
heap[c[i]].rt=merge(heap[c[i]].rt,i);
}
dep[1]=1;
dfs(1);
for(int i=1;i<=n;i++) printf("%d\n",ans1[i]);
for(int i=1;i<=m;i++) printf("%d\n",dep[c[i]]-dep[ans2[i]]);
return 0;
}