题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2809
思路
显然,选取需要工资最少的几个人最优。
枚举领导者的编号,问题就变成了求每个点的子树中工资能满足多少员工了。
很容易想到使用可并堆,如果选择建立小根堆会TLE,正解是选择建立大根堆,每次从这个点的子树中踢出需要工资最大的员工,如果被一个点的子节点踢出了,那么这个节点显然不会选择他。一步一步向上合并就可以A了。
代码
#include <cstdio>
#include <algorithm>
const int maxn=100000;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
struct node
{
node* son[2];
node* fa;
int val,dist;
};
node tnode[maxn+10];
node* root[maxn+10];
int n,m,cnt,nump[maxn+10],c[maxn+10],l[maxn+10];
long long giv[maxn+10],ans;
int pre[maxn+10],now[maxn+10],son[maxn+10],tot;
inline int upd_dist(node* now)
{
if(now->son[1]==NULL)
{
now->dist=0;
}
else
{
now->dist=now->son[1]->dist+1;
}
return 0;
}
node* merge(node* a,node* b)
{
if(a==NULL)
{
return b;
}
if(b==NULL)
{
return a;
}
if(a->val<b->val)
{
std::swap(a,b);
}
a->son[1]=merge(a->son[1],b);
if(a->son[1]!=NULL)
{
a->son[1]->fa=a;
}
if((a->son[0]!=NULL)&&(a->son[1]!=NULL)&&(a->son[0]->dist<a->son[1]->dist))
{
std::swap(a->son[0],a->son[1]);
}
else if((a->son[0]==NULL)&&(a->son[1]!=NULL))
{
a->son[0]=a->son[1];
a->son[1]=NULL;
}
upd_dist(a);
return a;
}
node* getf(node* now)
{
if(now->fa==NULL)
{
return now;
}
return getf(now->fa);
}
inline int getmax(node* x)
{
return getf(x)->val;
}
inline node* pop(node* x)
{
node* f=getf(x);
node* s=merge(f->son[0],f->son[1]);
s->fa=NULL;
return s;
}
inline int ins(int a,int b)
{
pre[++tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int dfs(int u)
{
root[u]=&tnode[++cnt];
root[u]->fa=root[u]->son[0]=root[u]->son[1]=NULL;
root[u]->val=c[u];
root[u]->dist=0;
giv[u]=c[u];
nump[u]=1;
int j=now[u];
while(j)
{
int v=son[j];
dfs(v);
root[u]=merge(root[u],root[v]);
giv[u]+=giv[v];
nump[u]+=nump[v];
j=pre[j];
}
while(giv[u]>m)
{
giv[u]-=getmax(root[u]);
--nump[u];
root[u]=pop(root[u]);
}
ans=std::max(ans,1ll*l[u]*nump[u]);
return 0;
}
int main()
{
n=read();
m=read();
for(int i=1; i<=n; ++i)
{
int f=read();
ins(f,i);
c[i]=read();
l[i]=read();
}
dfs(1);
printf("%lld\n",ans);
return 0;
}