[APIO2012]派遣
给你一棵树
在进行树形结构时,维护当前节点的左偏树
由于插入是logn的,删除是O(1)的
所以怎么乱搞都没问题
#include<bits/stdc++.h> #define re return #define ll long long #define inc(i,l,r) for(register int i=l;i<=r;++i) const int maxn=100005; using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,fa[maxn],hd[maxn],ls[maxn],rs[maxn],dist[maxn],size[maxn]; ll val[maxn],cost[maxn],ans,C[maxn]; struct node{ int to,nt; }e[maxn]; inline int find(int x) { re x==fa[x]?x:fa[x]=find(fa[x]); } inline int merge(int x,int y) { if(!x||!y)re x+y; if(cost[x]<cost[y])swap(x,y); int &ul=ls[x],&ur=rs[x]; ur=merge(ur,y); fa[ur]=x; if(dist[ul]<dist[ur])swap(ul,ur); dist[x]=dist[ur]+1; C[x]=C[ls[x]]+C[rs[x]]+cost[x]; size[x]=size[ls[x]]+size[rs[x]]+1; re x; } inline void dfs(int x) { for(int i=hd[x];i;i=e[i].nt) { int v=e[i].to; dfs(v); merge(find(v),find(x)); while(m<C[find(x)]) { int y=fa[x]; int z=merge(ls[y],rs[y]); fa[y]=fa[z]=z; } } ans=max(ans,val[x]*size[find(x)]); } int main() { int x; rd(n);rd(m); inc(i,1,n)fa[i]=i; dist[0]=-1; inc(i,1,n) { rd(x),rd(cost[i]),rd(val[i]); C[i]=cost[i];size[i]=1; e[i]=(node){i,hd[x]};hd[x]=i; } dfs(1); printf("%lld",ans); re 0; }