【BZOJ2809】[APIO2012] dispatching(左偏树例题)
大致题意: 有\(N\)名忍者,每名忍者有三个属性:上司\(B_i\),薪水\(C_i\)和领导力\(L_i\)。你要选择一个忍者作为管理者,然后在所有被他管理的忍者中选择若干名忍者,使薪水总和不超过预算\(M\)。现让你最大化被派遣的忍者总数乘以管理者的领导力水平。
关于左偏树
这道题是一道比较裸的左偏树板子题。
左偏树,主要用途是实现堆的合并,在这一类的题目中还是比较实用的。
大致思路
如果你会左偏树,那么这题就是一道水题。
首先考虑遍历题目中给出的树,然后对每一个节点开一个大根堆,每次把超过预算的多余部分弹出,更新\(ans\)之后再与父亲的堆进行合并。
一个细节就是当前节点可能会被弹出,所以我们要用\(Top_x\)来记录当前节点堆的堆顶,然后对\(Top_x\)进行操作。
代码
#include<bits/stdc++.h>
#define N 100000
#define swap(x,y) (x^=y^=x^=y)
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define LL long long
using namespace std;
int n,m,ee=0,lnk[N+5],Top[N+5],cnt[N+5],Cost[N+5],Val[N+5];LL ans=0,tot[N+5];
struct edge
{
int to,nxt;
}e[N+5];
class FIO
{
private:
#define Fsize 100000
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
#define pc(ch) (void)(putchar(ch))
int Top,FoutSize;char ch,*A,*B,Fin[Fsize],Fout[Fsize],Stack[Fsize];
public:
inline void read(int &x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));}
inline void write(LL x) {if(!x) return pc('0');while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}
}F;
class Class_LeftistTree//左偏树模板
{
private:
struct Tree
{
int Val,Dis,Exist,Father,Son[2];
Tree(int x=0):Val(x){Dis=Father=Son[0]=Son[1]=0,Exist=1;}
}node[N+5];
inline int Merge(int x,int y)
{
if(!x||!y) return x+y;
if(node[x].Val<node[y].Val) swap(x,y);
if(node[node[x].Son[1]=Merge(node[x].Son[1],y)].Father=x,node[node[x].Son[0]].Dis<node[node[x].Son[1]].Dis) swap(node[x].Son[0],node[x].Son[1]);
return node[x].Dis=node[node[x].Son[1]].Dis+1,x;
}
inline int TopPos(int x) {while(node[x].Father) x=node[x].Father;return x;}
public:
Class_LeftistTree() {node[0].Dis=-1,node[0].Exist=0;}
inline void Init(int n,int *data) {for(register int i=1;i<=n;++i) node[i]=Tree(data[i]);}
inline void Union(int x,int y) {if((x=TopPos(x))^(y=TopPos(y))&&node[x].Exist&&node[y].Exist) Merge(x,y);}
inline int PopTop(int x) {return node[x=TopPos(x)].Val=node[x].Dis=-1,node[x].Exist=0,node[node[x].Son[0]].Father=node[node[x].Son[1]].Father=0,Merge(node[x].Son[0],node[x].Son[1]);}
inline int TopVal(int x) {return node[TopPos(x)].Val;}
}LeftistTree;
inline void dfs(int x)//遍历
{
register int i;
for(i=lnk[Top[x]=x],tot[x]=Cost[x],cnt[x]=1;i;i=e[i].nxt) dfs(e[i].to),LeftistTree.Union(x,Top[e[i].to]),tot[x]+=tot[e[i].to],cnt[x]+=cnt[e[i].to];//先遍历子节点,然后从子节点更新信息
while(tot[x]>m) tot[x]-=LeftistTree.TopVal(Top[x]),--cnt[x],Top[x]=LeftistTree.PopTop(Top[x]);//弹出多余的元素
Gmax(ans,1LL*Val[x]*cnt[x]);//更新ans
}
int main()
{
register int i,x,rt;
for(F.read(n),F.read(m),i=1;i<=n;++i) F.read(x),F.read(Cost[i]),F.read(Val[i]),(x?add(x,i):rt=i);
return LeftistTree.Init(n,Cost),dfs(rt),F.write(ans),0;
}
【BZOJ2809】[APIO2012] dispatching(左偏树例题)的更多相关文章
- bzoj2809 [Apio2012]dispatching(左偏树)
[Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 M ...
- bzoj2809 [Apio2012]dispatching——左偏树(可并堆)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2809 思路有点暴力和贪心,就是 dfs 枚举每个点作为管理者: 当然它的子树中派遣出去的忍者 ...
- 【bzoj2809】[Apio2012]dispatching 左偏树
2016-05-31 15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...
- [Apio2012]dispatching 左偏树
题目描述 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增 ...
- [Apio2012]dispatching 左偏树做法
http://codevs.cn/problem/1763/ 维护子树大根堆,当子树薪水和>m时,删除最贵的点 #include<cstdio> #include<iostre ...
- APIO2012 派遣dispatching | 左偏树
题目链接:戳我 就是尽可能地选取排名小的,加起来就可以了.然后我们考虑利用一个大根堆,一个一个合并,如果超过派遣的钱,我们就把费用最大的那个忍者丢出队列. 左偏树,作为一个十分优秀的可并堆,我们这道题 ...
- BZOJ2809 dispatching(左偏树)
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...
- [APIO2012]派遣 左偏树
P1552 [APIO2012]派遣 题面 考虑枚举每个节点作为管理者,计算所获得的满意程度以更新答案.对于每个节点的计算,贪心,维护一个大根堆,每次弹出薪水最大的人.这里注意,一旦一个人被弹出,那么 ...
- 洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]
题目传送门 忍者 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都 ...
随机推荐
- sg函数和nim游戏的关系
sg函数和nim游戏的关系 本人萌新,文章如有错漏请多多指教-- 我在前面发了关于nim游戏的内容,也就是说给n堆个数不同的石子,每次在某个堆中取任意个数石子,不能取了就输了.问你先手是否必胜.然后只 ...
- Miller-Rabin素性测试|Pollard's Rho算法
Miller-Rabin 素性测试 Miller-Rabin 素数测试 一本通上的M-R不透彻啊~ Miller-Rabin是利用随机化算法判断一个数是合数还是素数. 首先,如果一个数N是素数,那么他 ...
- Ubuntu 防火墙IP转发做NAT,内网集群共享网络(简单)
服务器架构: 系统: Ubuntu 16.04 x64 使用自带防火墙 UFW 操作: 在有公网的服务器上,进行防火墙基本操作开启自己所需业务的端口,并按下方设置启动NAT: 其他内网机器修改网关或者 ...
- FoundToday 隐私政策
FoundToday 隐私政策 本应用尊重并保护所有使用服务用户的个人隐私权.为了给您提供更准确.更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息.但本应用将以高度的勤勉.审慎义 ...
- 洛谷 P1365 WJMZBMR打osu! / Easy
题目背景 原 维护队列 参见P1903 题目描述 某一天\(WJMZBMR\)在打\(osu~~~\)但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则 有\(n\)次点击要做,成功 ...
- js unicode
参考 http://www.ruanyifeng.com/blog/2014/12/unicode.html
- Shell面试,笔试整理
1.经典Shell脚本面试问题:https://blog.csdn.net/hyszyl/article/details/60970307
- 转 xshell 图像化展示
http://www.cnblogs.com/kellyseeme/p/7965830.html 限制: 无法显示通过堡垒机登录的机器的图形接界面. 只能显示直接登录的服务到期的图像化界面 Xshel ...
- bootstrap栅格系统的实现
bootstrap提供了一个非常实用的栅格系统,可以实现响应式的网格布局,原理其实很简单,利用了float.百分比的宽度和@media的配合实现响应式,bootstrap默认把一行分为了12列,提供了 ...
- 利用Python进行数据分析 2017 第二版 项目代码
最近在学习<利用Python进行数据分析>,找到了github项目的地址, 英文版本,中文版本 (非常感谢翻译中文的作者). mark一下,方便后边学习查找.