[bzoj 2809][Apio2012]dispatching
传送门
Solution
可并堆——左偏树 的模板题
维护大根堆,这样只要达到雇佣薪水的上限,就直接pop堆顶元素就行了
Code
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define MN 100005
int Li[MN],fa[MN],Ci[MN];
int ls[MN],rs[MN],M,val[MN],siz[MN],rt[MN],dis[MN];
ll ans,sum[MN];
struct edge{int to,nex;}e[MN];int hr[MN],en;
inline void ins(int f,int t){e[++en]=(edge){t,hr[f]};hr[f]=en;}
int Merge(int x,int y)
{
if(!x||!y) return x|y;
if(val[x]<val[y]) std::swap(x,y);
rs[x]=Merge(rs[x],y);
if(dis[rs[x]]>dis[ls[x]]) std::swap(ls[x],rs[x]);
dis[x]=dis[rs[x]]+1;
sum[x]=sum[ls[x]]+sum[rs[x]]+val[x];
siz[x]=siz[ls[x]]+siz[rs[x]]+1;
return x;
}
inline void Pop(int &x){x=Merge(ls[x],rs[x]);}
void dfs(int x)
{
register int i;
for(i=hr[x];i;i=e[i].nex)
{
dfs(e[i].to),rt[x]=Merge(rt[x],rt[e[i].to]);
while(sum[rt[x]]>M) Pop(rt[x]);
}
ans=max(ans,1ll*Li[x]*siz[rt[x]]);
}
int main()
{
register int n,i;
n=read(),M=read();
for(i=1;i<=n;++i) fa[i]=read(),Ci[i]=read(),Li[i]=read(),ins(fa[i],i);
for(i=1;i<=n;++i) if(Ci[i]<=M) rt[i]=i,sum[i]=val[i]=Ci[i],dis[i]=siz[i]=1;
dfs(1);
printf("%lld\n",ans);
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
致虚极,守静笃,万物并作,吾以观其复