[BZOJ 2809] Dispatching
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2809
Algorithm:
很容易看出此题贪心的思路:
只要在每个点的子树中贪心选取费用最小的,使其总和不超过m即可
维护最小值,想到用堆,但普通的堆无法进行合并
于是用到数据结构可并堆/左偏树来在O(logN)的时间内合并堆
可并堆和左偏树的区别仅仅在于左偏树多维护了dist数组,而可并堆是无脑交换左右子树
这也使得左偏树的复杂度是能证明的O(logN),而可并堆仅仅是均摊复杂度为O(logN),因此还是尽量用左偏树吧
证明:n个节点的左偏树的距离dist最大为log(n+1)-1
若左偏树的距离为一定值,则节点数最少的左偏树是完全二叉树。
设一棵左偏树的距离为k,则这棵左偏树至少有2^{k+1}-1个节点。
因为n>=2^{k+1}-1,所以k<=log(n+1)-1
Code:
左偏树:
#include <bits/stdc++.h> using namespace std;
typedef long long ll; inline int read()
{
char ch;int num,f=;
while(!isdigit(ch=getchar())) f|=(ch=='-');
num=ch-'';
while(isdigit(ch=getchar())) num=num*+ch-'';
return f?-num:num;
} const int MAXN=1e5+;
vector<int> G[MAXN];
struct LTree
{
int ls,rs,dist,val;
ll siz,sum;
}Lt[MAXN]; int n,m,C[MAXN],L[MAXN],root[MAXN];
ll res=; int merge(int x,int y)
{
if(!x || !y) return x+y;
if(Lt[x].val<Lt[y].val) swap(x,y);
Lt[x].rs=merge(Lt[x].rs,y); if(Lt[Lt[x].ls].dist<Lt[Lt[x].rs].dist) swap(Lt[x].ls,Lt[x].rs);
Lt[x].dist=Lt[Lt[x].rs].dist+;
Lt[x].siz=Lt[Lt[x].rs].siz+Lt[Lt[x].ls].siz+;
Lt[x].sum=Lt[Lt[x].rs].sum+Lt[Lt[x].ls].sum+Lt[x].val; return x;
} void pop(int &x)
{
x=merge(Lt[x].ls,Lt[x].rs);
} void dfs(int x)
{
root[x]=x;
for(int i=;i<G[x].size();i++)
dfs(G[x][i]),root[x]=merge(root[x],root[G[x][i]]);
while(Lt[root[x]].siz && Lt[root[x]].sum>m) pop(root[x]);
res=max(res,L[x]*Lt[root[x]].siz);
} int main()
{
n=read();m=read();
for(int i=;i<=n;i++)
{
int x=read();G[x].push_back(i);
C[i]=read();L[i]=read();
Lt[i].sum=Lt[i].val=C[i];Lt[i].siz=;
} dfs();
cout << res;
return ;
}
可并堆:
#include <bits/stdc++.h> using namespace std;
typedef long long ll; inline int read()
{
char ch;int num,f=;
while(!isdigit(ch=getchar())) f|=(ch=='-');
num=ch-'';
while(isdigit(ch=getchar())) num=num*+ch-'';
return f?-num:num;
} const int MAXN=1e5+;
vector<int> G[MAXN]; int n,m,C[MAXN],L[MAXN],root[MAXN];
ll res=; struct SkewHeap
{
int v[MAXN],ls[MAXN],rs[MAXN];
ll siz[MAXN],sum[MAXN]; int merge(int x,int y)
{
if(!x || !y) return x+y;
if(v[x]<v[y]) swap(x,y);
rs[x]=merge(rs[x],y);
swap(ls[x],rs[x]); sum[x]=sum[ls[x]]+sum[rs[x]]+v[x];
siz[x]=siz[ls[x]]+siz[rs[x]]+;
return x;
} void pop(int &x){x=merge(ls[x],rs[x]);}
}Heap; void dfs(int x)
{
root[x]=x;
for(int i=;i<G[x].size();i++)
dfs(G[x][i]),root[x]=Heap.merge(root[x],root[G[x][i]]);
while(Heap.siz[root[x]] && Heap.sum[root[x]]>m) Heap.pop(root[x]);
res=max(res,L[x]*Heap.siz[root[x]]);
} int main()
{
n=read();m=read();
for(int i=;i<=n;i++)
{
int x=read();G[x].push_back(i);
C[i]=read();L[i]=read();
Heap.siz[i]=;Heap.sum[i]=Heap.v[i]=C[i];
} dfs();
cout << res;
return ;
}
Review:
1、对于每棵左偏树,最好用root[x]记录其根节点
2、对于左偏树要跟着维护的信息,
在merge的最后进行更新
3、可选择将整个数据结构封装在一个类中,写起来可能方便点
[BZOJ 2809] Dispatching的更多相关文章
- BZOJ - 2809 dispatching 主席树+dfs序
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...
- 【BZOJ 2809 dispatching】
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 4393 Solved: 2246[Submit][Status][Discuss] Descript ...
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...
- bzoj 2809: [Apio2012]dispatching -- 可并堆
2809: [Apio2012]dispatching Time Limit: 10 Sec Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...
- 【BZOJ 2809】2809: [Apio2012]dispatching (左偏树)
2809: [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Maste ...
- AC日记——dispatching bzoj 2809
2809: [Apio2012]dispatching Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3290 Solved: 1740[Submi ...
- BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆
题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定 ...
- BZOJ 2809: [Apio2012]dispatching(左偏树)
http://www.lydsy.com/JudgeOnline/problem.php?id=2809 题意: 思路:最简单的想法就是枚举管理者,在其子树中从薪水低的开始选起,但是每个节点都这样处理 ...
- BZOJ 2809 [Apio2012]dispatching(斜堆+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2809 [题目大意] 给出一棵树,求出每个点有个权值,和一个乘算值,请选取一棵子树, 并 ...
随机推荐
- Ubuntu下使用mysqli-connect连接mysql时报错:ERROR 1698 (28000): Access denied for user 'root'@'localhost'
LNMP安装好后,写了个index.php文件,里面的内容很简单,就是想测试php与mysql的通信是否正常,代码如下: <?php $host = 'localhost'; $user = ' ...
- [hdu 1067]bfs+hash
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1067 queue里面果然不能放vector,还是自己写的struct比较省内存…… #include& ...
- 初识 spl_autoload_register
spl_autoload_register 一.首先我们看来自官网的定义 版本要求:php版本为5.1.2+ 说明:注册给定的函数作为__autoload的实现.即自动加载 函数参数说明: bool ...
- PhoneGap之自定义插件
PhoneGap:作为原生App,Java(这里面是指Android的)与JavaScript 的通信桥梁,使得我们的混合开发更加得心应手,我是与Android结合的混合开发. 但在这里不得不吐槽一下 ...
- java JDK动态代理的机制
一:前言 自己在稳固spring的一些特性的时候在网上看到了遮掩的一句话“利用接口的方式,spring aop将默认通过JDK的动态代理来实现代理类,不适用接口时spring aop将使用通过cgli ...
- [洛谷P2124] 奶牛美容
洛谷题目链接:奶牛美容 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 6 16 ................ ..XXXX....XXX... ...XXXX... ...
- HDU 1798 Tell me the area (数学)
题目链接 Problem Description There are two circles in the plane (shown in the below picture), there ...
- NYOJ 127 星际之门(一) (数学)
题目链接 描述 公元3000年,子虚帝国统领着N个星系,原先它们是靠近光束飞船来进行旅行的,近来,X博士发明了星际之门,它利用虫洞技术,一条虫洞可以连通任意的两个星系,使人们不必再待待便可立刻到达目的 ...
- Jackson对多态和多子类序列化的处理配置
目录 Jackson 多态类型的处理 Jackson Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象. 多态类型的处理 jacks ...
- python收集
http://my.oschina.net/mutour/blog/?disp=2&catalog=0&sort=time&p=4 Python 不使用win32api打开任务 ...