BZOJ2809:[Apio2012]dispatching——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2809
题面复制于:https://www.luogu.org/problemnew/show/1552
题目背景
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。
题目描述
在这个帮派里,有一名忍者被称之为Master。除了Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。
现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,你就不需要支付管理者的薪水。
你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。
写一个程序,给定每一个忍者i的上级Bi,薪水Ci,领导力Li,以及支付给忍者们的薪水总预算M,输出在预算内满足上述要求时顾客满意度的最大值。
输入输出格式
输入格式:
第一行包含两个整数N和M,其中N表示忍者的个数,M表示薪水的总预算。
接下来N行描述忍者们的上级、薪水以及领导力。其中的第i行包含三个整数Bi,Ci,Li分别表示第i个忍者的上级,薪水以及领导力。Master满足Bi=0,并且每一个忍者的老板的编号一定小于自己的编号Bi<i。
输出格式:
输出一个数,表示在预算内顾客的满意度的最大值。
输入输出样例
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
6
——————————————————————————————
我们将关系图建出来,发现我们需要找到最大的子树的根节点L*选取的点的个数,同时使得费用不超过m。
显然对于同一棵子树,我们取相同个数的节点,显然最优的就是取费用最小的点,去掉费用大的点。
显然我们可以用左偏树维护子树中最大费用节点,同时我们还可以顺便维护子树的节点数。
好了做完了……
但是细节很多让我们慢慢讲:
1.方便起见,我们按照建好的关系树从下往上造左偏树。
2.每当树的费用大于m的时候将根节点剔除(左右节点,权值,节点数=0),将其左右子树合并,再将原来根节点合并进来(这是为了方便我们操作,这样我们对于一个节点i,我们直接tr[find(i)].sum*l[i]就是结果,不需要别的操作)
3.那么我们就需要维护每个节点在左偏树的爸爸了,请注意使用路径压缩。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cctype>
#include<queue>
using namespace std;
const int N=1e5+;
typedef long long ll;
inline ll read(){
ll X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to;
int nxt;
}edge[N];
int cnt=,head[N];
void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
int fa[N],root;
ll n,m,l[N];
struct tree{
int l,r,f;
ll dis,val,size,sum;
}tr[N];
int merge(int x,int y){
if(x==||y==)return x+y;
if(tr[x].val<tr[y].val)
swap(x,y);
tr[x].r=merge(tr[x].r,y);
tr[tr[x].r].f=x;
if(tr[tr[x].l].dis<tr[tr[x].r].dis)
swap(tr[x].l,tr[x].r);
tr[x].dis=tr[tr[x].r].dis+;
tr[x].size=(tr[x].l?tr[tr[x].l].size:)+(tr[x].r?tr[tr[x].r].size:)+(tr[x].size?:);
tr[x].sum=(tr[x].l?tr[tr[x].l].sum:)+(tr[x].r?tr[tr[x].r].sum:)+tr[x].val;
return x;
}
int q[N],r;
inline int find(int x){
if(!tr[x].f)return x;
return tr[x].f=find(tr[x].f);
}
ll solve(){
ll ans=;
q[r=]=root;
for(int left=;left<=r;left++){
for(int k=head[q[left]];k;k=edge[k].nxt){
int v=edge[k].to;
r++;q[r]=v;
}
}
for(int i=r;i>=;i--){
int x=q[i],y=fa[x];
ans=max(ans,tr[find(x)].size*l[x]);
x=merge(find(x),find(y));
while(tr[x].sum>m){
tr[x].val=tr[x].sum=tr[x].size=;
int ls=tr[x].l,rs=tr[x].r;
tr[ls].f=tr[rs].f=tr[x].l=tr[x].r=;
x=merge(x,merge(ls,rs));
}
}
ans=max(ans,tr[find(root)].size*l[root]);
return ans;
}
void reset(int x,ll c){
tr[x].val=tr[x].sum=c;
tr[x].r=tr[x].l=tr[x].dis=tr[x].f=;
tr[x].size=;
return;
}
int main(){
n=read();
m=read();
tr[].dis=-;
for(int i=;i<=n;i++){
fa[i]=read();
reset(i,read());
l[i]=read();
if(!fa[i])root=i;
else add(fa[i],i);
}
printf("%lld\n",solve());
return ;
}
BZOJ2809:[Apio2012]dispatching——题解的更多相关文章
- bzoj2809 [Apio2012]dispatching(左偏树)
[Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 M ...
- BZOJ2809: [Apio2012]dispatching
传送门 主席树经典题. 首先把树搞出来,然后搞出来DFS序.然后离散化点权,在DFS序上建立主席树. 对于每个点对应的区间,查找对应的区间最大的点数即可. //BZOJ2809 //by Cydiat ...
- BZOJ2809 [Apio2012]dispatching 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2809 题意概括 n个点组成一棵树,每个点都有一个领导力和费用,可以让一个点当领导,然后在这个点的子 ...
- BZOJ2809——[Apio2012]dispatching
1.题目大意:给一棵树和M值,每个点有两个权值C和L,选x个点,这x个点的C值的和不能超过M,且这x个点如果都在某个子树内 定义满意度为x*这个子树的根的L值 2.分析:这是一道可并堆的题目,我们考虑 ...
- [BZOJ2809][Apio2012]dispatching(左偏树)
首先对于一个节点以及它的子树,它的最优方案显然是子树下选最小的几个 用左偏树维护出每棵子树最优方案的节点,记录答案 然后它的这棵树可以向上转移给父节点,将所有子节点的左偏树合并再维护就是父节点的最优方 ...
- 【DFS序】【莫队算法】【权值分块】bzoj2809 [Apio2012]dispatching
题意:在树中找到一个点i,并且找到这个点子树中的一些点组成一个集合,使得集合中的所有点的c之和不超过M,且Li*集合中元素个数和最大 首先,我们将树处理出dfs序,将子树询问转化成区间询问. 然后我们 ...
- bzoj2809 [Apio2012]dispatching——左偏树(可并堆)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2809 思路有点暴力和贪心,就是 dfs 枚举每个点作为管理者: 当然它的子树中派遣出去的忍者 ...
- [BZOJ2809][Apio2012]dispatching 贪心+可并堆
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 我们考虑以每一个节点作为管理者所得的最优答案,一定是优先选择所要薪水少的忍者.那么首 ...
- 【BZOJ2809】[Apio2012]dispatching 可并堆
[BZOJ2809][Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 M ...
随机推荐
- 提权基础-----mysql-udf提权
1.总结关于udf提权方法 通过弱口令,爆破,网站配置文件等方式得到mysql数据库帐号密码,---还要能外连 (1).将udf.dll代码的16进制数声明给my_udf_a变量 set @my_ud ...
- Unity 特殊目录
其他目录 Application.persistentDataPath:webGL平台只能使用这个
- 关于java中的“error: bad operand types for binary operator ”
今天做这个题目的时候(142. O(1) Check Power of 2),遇到一个错误“ bad operand types for binary operator '&' ”. 先贴一下 ...
- CodeForces 838B Diverging Directions 兼【20180808模拟测试】t3
描述 给你一个图,一共有 N 个点,2*N-2 条有向边. 边目录按两部分给出 1. 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点到达. 2. 接下来的 N-1 ...
- Liunx 基本命令
find : find ./ -name "*instantiate_post_check.yml*" grep: openstack network show fe92bfcf- ...
- 2018(容斥定理 HDU6286)
2018 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- centos+nginx+redmine+gitosis安装指南
说明 这篇文章我现在的主要目的是记录自己安装redmine和gitosis的过程,可能写的有些糙,请各位读者见谅.我会在后面的时间里逐渐完善细节.但我想,这已经是网上迄今为止国内最详细的nginx+r ...
- Eclipse安装颜色主题,个性化你的IDE,让你的IDE焕然一新
我们都知道eclipse默认的颜色主题是白色的背景,但是如果想改变代码编辑区的背景颜色,需要怎么办呢? 今天给大家介绍一个非常赞的eclipse,可以很方便的根据自己的需求选择喜欢的颜色主题,其他的不 ...
- sqoop-1.4.6安装与使用
一.安装 1.下载sqoop-1.4.6-bin.tar.gz并解压 2.修改conf/sqoop-env.sh,设置如下变量: export HADOOP_COMMON_HOME=/usr/loca ...
- 【web前端开发】浏览器兼容性处理大全
1.居中问题 div里的内容,IE默认为居中,而FF默认为左对齐,可以尝试增加代码margin: 0 auto; 2.高度问题 两上下排列或嵌套的div,上面的div设置高度(height),如果di ...