P1552 [APIO2012] 派遣

P1552 [APIO2012] 派遣

题目背景

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。

题目描述

在这个帮派里,有一名忍者被称之为 Master。除了 Master 以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。

现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,你就不需要支付管理者的薪水。

你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。

写一个程序,给定每一个忍者 i 的上级 Bi,薪水 Ci,领导力 Li,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。

提示

1N1051M1090Bi<i1CiM1Li109

Solution:

十分简单的线段树合并.

对于每个点开一颗权值线段树来维护其子树下的薪水 C 的分布情况,然后向上合并。

对于答案统计,查询在改点下以 m 的代价能派遣的最多忍者数 tmp 然后 ansx=tmpxLx

然后这题就欢乐的做完了

Code:

#include<bits/stdc++.h>
#define ll long long
const int N=1e5+5;
const int inf=1e9;
using namespace std;
struct Segment_Tree{
int rt[N],cnt;
struct Tree{
int ls,rs,cnt;
ll val;
}t[N*40];
void pushup(int x)
{
t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt;
t[x].val=t[t[x].ls].val+t[t[x].rs].val;
}
int merge(int x,int y,int l,int r)
{
if(!x||!y)return x|y;
if(l==r){t[x].cnt+=t[y].cnt,t[x].val+=t[y].val;return x;}
int mid=l+r>>1;
t[x].ls=merge(t[x].ls,t[y].ls,l,mid);
t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r);
pushup(x);
return x;
}
void insert(int &x,int l,int r,int pos)
{
t[x= (x ? x : ++cnt)].cnt++;
t[x].val+=pos;
if(l==r)return ;
int mid=l+r>>1;
if(pos<=mid)insert(t[x].ls,l,mid,pos);
if(mid<pos)insert(t[x].rs,mid+1,r,pos);
}
void query(int x,int l,int r,int &k,ll &res)
{
if(!x||!k)return;
if(t[x].val<=k){k-=t[x].val,res+=t[x].cnt;return ;}
if(l==r)
{
if(k<t[x].val){res+=k/l,k=0;}
return;
}
int mid=l+r>>1;
if(l<=k)
query(t[x].ls,l,mid,k,res);
if(mid+1<=k)
query(t[x].rs,mid+1,r,k,res);
return;
}
}T;
struct Edge{
int y,nxt;
}e[N<<1];
int head[N];
void add(int x,int y)
{
e[++head[0]]=Edge{y,head[x]};head[x]=head[0];
}
int cost[N],lead[N];
int n,m;
ll ans;
inline ll Max(ll x,ll y){return x>y ? x : y;}
void dfs(int x)
{
T.insert(T.rt[x],1,inf,cost[x]);
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].y;
dfs(y);
T.merge(T.rt[x],T.rt[y],1,inf);
}
ll tmp=0;
int k=m;
T.query(T.rt[x],1,inf,k,tmp);
tmp=1ll*tmp*lead[x];
//cout<<x<<"="<<tmp<<"\n";
ans = Max(ans,tmp);
}
void work()
{
cin>>n>>m;
for(int y=1,x;y<=n;y++)
{
scanf("%d%d%d",&x,&cost[y],&lead[y]);
add(x,y);
}
dfs(1);
printf("%lld",ans);
}
int main()
{
//freopen("dispatch.in","r",stdin);freopen("dispatch.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示