P1552 [APIO2012] 派遣
P1552 [APIO2012] 派遣
题目背景
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。
题目描述
在这个帮派里,有一名忍者被称之为 Master。除了 Master 以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。
现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,你就不需要支付管理者的薪水。
你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。
写一个程序,给定每一个忍者
提示
Solution:
十分简单的线段树合并.
对于每个点开一颗权值线段树来维护其子树下的薪水
对于答案统计,查询在改点下以
然后这题就欢乐的做完了
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; }