洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]
忍者
Description
Input
Output
Sample Input
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
Sample Output
HINT
如果我们选择编号为 1的忍者作为管理者并且派遣第三个和第四个忍者,薪水总和为 4,没有超过总预算4。因为派遣了 2 个忍者并且管理者的领导力为 3,用户的满意度为 2 ,是可以得到的用户满意度的最大值。
分析:
这个题意描述是真的有点迷。。一句话题意:从树中选出一个节点作为管理者,然后在它的子树中(包括它自己)选出若干节点,要求使花费总和小于$m$,并且使得收益最大。
我们可以用左偏树维护点的关系。
除了左右子节点和高度以外,这个左偏树一共还需要维护该节点花费,总花费,总人数三条信息。从根节点开始$dfs$,然后从下往上递归转移。当转移到第$x$个节点时,我们将它与它所有子节点形成的左偏树合并,然后进行判断,将花费大的节点全部弹出知道花费小于等于$m$为止,然后更新答案即可。当然,这里左偏树要建立大根堆,因为小根堆维护花费和不大于$m$会非常麻烦。然后注意一些细节就行了。
Code:
//It is made by HolseLee on 14th Aug 2018
//Luogu.org P1552
#include<bits/stdc++.h>
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
#define Swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b)
using namespace std; typedef long long ll;
const int N=1e5+;
int n,head[N],size,rt[N];
ll m,c[N],p[N],ans;
struct node{
int to,nxt;
}edge[N<<];
struct Node{
ll sum,val;int ls,rs,height,siz;
}t[N];
struct Leftist{
int merge(int x,int y)
{
if(!x||!y)return x+y;
if(t[y].val>t[x].val)Swap(x,y);
int &r=t[x].rs,&l=t[x].ls;
r=merge(r,y);
if(t[r].height>t[l].height)swap(l,r);
t[x].height=t[r].height+;
t[x].sum=t[l].sum+t[r].sum+t[x].val;
t[x].siz=t[l].siz+t[r].siz+;
return x;
} int delet(int x)
{
return merge(t[x].ls,t[x].rs);
}
}T; inline int read()
{
char ch=getchar();int num=;bool flag=false;
while(ch<''||ch>''){if(ch=='-')flag=true;ch=getchar();}
while(ch>=''&&ch<=''){num=num*+ch-'';ch=getchar();}
return flag?-num:num;
} inline void add(int x,int y)
{
edge[++size].to=y;
edge[size].nxt=head[x];
head[x]=size;
} void dfs(int u,int fa)
{
t[u].val=t[u].sum=c[u];
t[u].ls=t[u].rs=t[u].height=;
t[u].siz=;
rt[u]=u;int v;
for(int i=head[u];i!=-;i=edge[i].nxt){
v=edge[i].to;
if(v==fa)continue;
dfs(v,u);
rt[u]=T.merge(rt[u],rt[v]);
}
while(t[rt[u]].sum>m&&t[rt[u]].siz!=)
rt[u]=T.delet(rt[u]);
ans=Max(ans,t[rt[u]].siz*p[u]);
} int main()
{
n=read();m=read();
int x;
memset(head,-,sizeof(head));
for(int i=;i<=n;++i){
x=read();c[i]=read();p[i]=read();
add(x,i);add(i,x);
}
dfs(,);
printf("%lld",ans);
return ;
}
洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]的更多相关文章
- [洛谷P1552] [APIO2012]派遣(左偏树)
这道题是我做的左偏树的入门题,奈何还是看了zsy大佬的题解才能过,唉,我太弱了. 左偏树总结 Part 1 理解题目 很显然,通过管理关系的不断连边,最后连出来的肯定是一棵树,那么不难得出,当一个忍者 ...
- 洛谷P1552 [APIO2012]派遣(左偏树)
传送门 做这题的时候现学了一波左偏树2333(好吧其实是当初打完板子就给忘了) 不难发现肯定是选子树里权值最小的点且选得越多越好 但如果在每一个点维护一个小根堆,我们得一直找知道权值大于m为止,时间会 ...
- [APIO2012]派遣 左偏树
P1552 [APIO2012]派遣 题面 考虑枚举每个节点作为管理者,计算所获得的满意程度以更新答案.对于每个节点的计算,贪心,维护一个大根堆,每次弹出薪水最大的人.这里注意,一旦一个人被弹出,那么 ...
- 2018.07.31洛谷P1552 [APIO2012]派遣(可并堆)
传送门 貌似是个可并堆的模板题,笔者懒得写左偏堆了,直接随机堆水过.实际上这题就是维护一个可合并的大根堆一直从叶子合并到根,如果堆中所有数的和超过了上限就一直弹直到所有数的和不超过上限为止,最后对于当 ...
- [洛谷P1552][APIO2012]派遣
题目大意:有一棵$n$个点的树,和一个费用$m$,每个点有一个费用和价值,请选一个点,再从它的子树中选取若干个点,使得那个点的价值乘上选的点的个数最大,要求选的点费用总和小于等于$m$ 题解:树形$d ...
- 洛谷P4103 [HEOI2014]大工程(虚树 树形dp)
题意 链接 Sol 虚树. 首先建出虚树,然后直接树形dp就行了. 最大最小值直接维护子树内到该节点的最大值,然后合并两棵子树的时候更新一下答案. 任意两点的路径和可以考虑每条边两边的贡献,\(d[x ...
- 洛谷1552 [APIO2012]派遣
洛谷1552 [APIO2012]派遣 原题链接 题解 luogu上被刷到了省选/NOI- ...不至于吧 这题似乎有很多办法乱搞? 对于一个点,如果他当管理者,那选的肯定是他子树中薪水最少的k个,而 ...
- 洛谷 - P1552 - 派遣 - 左偏树 - 并查集
首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...
- P1552 派遣 左偏树
左偏树就是一个应该用堆维护的区间,然后需要进行合并操作而发明的算法,其实这个算法没什么难的,和树剖有点像,维护几个数值,然后递归回来的时候就可以修改. 题干: 题目背景 在一个忍者的帮派里,一些忍者们 ...
随机推荐
- package.json文档
之前在博客中写过一篇关于 " node.js的安装配置 " 的文章,里面有提到利用 gulp watch 来监听文档的变化.其中需要 package.json 文件才能实现效果,所 ...
- HDU 1930 CRT
也是很模板的一道题,给出一些数,分割,模数固定是4个互质的. /** @Date : 2017-09-16 23:54:51 * @FileName: HDU 1930 CRT.cpp * @Plat ...
- Spring Cacheable 注解不缓存null值
用Cacheable注解时,发现空值,也会被缓存下来.如果我们期望空值不被缓存,可以做如下设置: @Cacheable(key = "#id", unless="#res ...
- Productivity tips, tricks and hacks for academics (2015 edition)
Productivity tips, tricks and hacks for academics (2015 edition) Contents Jump to: My philosophy: Op ...
- Uploadify & jQuery.imgAreaSelect 插件实现图片上传裁剪
在网站中需要一个图片上传裁剪的功能,借鉴这篇文章 Ajax+PHP+jQuery图片截图上传 的指点,找到了jquery.imgAreaSelect这个不错插件,能对图片进行自定义区域选择并给出坐标, ...
- NYOJ 1272 表达式求值 第九届省赛 (字符串处理)
title: 表达式求值 第九届省赛 nyoj 1272 tags: [栈,数据结构] 题目链接 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表 ...
- java检验银行卡号
/* 校验过程: 1.从卡号最后一位数字开始,逆向将奇数位(1.3.5等等)相加. 2.从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,将个位十位数字相加,即将其减去9),再求和 ...
- Python3中对Dict的内存优化
众所周知,python3.6这个版本对dict的实现是做了较大优化的,特别是在内存使用率方面,因此我觉得有必要研究一下最新的dict的源码实现. 前后断断续续看了大概一周多一点,主要在研究dict和创 ...
- Ubuntu10.04 下安装RabbitVCS
安装RabbitVCS的方法步骤如下: 1.sudo add-apt-repository ppa:rabbitvcs/ppa #将rabbitvcs的添加到源里面.(次操作会提示是否要添 ...
- git-定制属于你的log格式
软件版本: 操作系统:ubuntu10.04 内核版本:Linux version 2.6.32-36-generic git 版本:git version 1.7.0.4 1. ...