题解:
将所有骑士放在$ci$上,然后树上$dfs$。
每个节点维护一个小根堆,一直$pop$直到$top>=hi$。
然后放加法、乘法标记,将剩下的骑士回溯带回父节点。
代码:
#include#include #include using namespace std;typedef long long ll;const int N = 300050;template inline void read(T&x){ T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c;}int n,m,f[N],hed[N],cnt;ll h[N],a[N],v[N],s[N],c[N],tag_p[N],tag_m[N];int dis[N],ls[N],rs[N];int rt[N];struct EG{ int to,nxt;}e[N];void ae(int f,int t){ e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt;}void add(int x,ll d){ if(!x)return ; tag_p[x]+=d; s[x]+=d;}void mul(int x,ll d){ if(!x)return ; tag_m[x]*=d; tag_p[x]*=d; s[x]*=d;}void pushdown(int x){ if(tag_m[x]!=1) { mul(ls[x],tag_m[x]); mul(rs[x],tag_m[x]); tag_m[x] = 1; } if(tag_p[x]) { add(ls[x],tag_p[x]); add(rs[x],tag_p[x]); tag_p[x] = 0; }}int merge(int x,int y){ if(!x||!y)return x+y; if(s[x]>s[y])swap(x,y); pushdown(x); rs[x] = merge(rs[x],y); if(dis[ls[x]]