[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 [题目大意] 给出一棵树,求出每个点有个权值,和一个乘算值,请选取一棵子树, 并 ...
随机推荐
- fscanf函数的应用
转摘自:http://blog.csdn.net/mxgsgtc/article/details/13005675 以前老是被从文本里读取文件,然后逐个的进行字符解析,感觉非常的慢,自从知道了fsca ...
- wait , notify 模拟 Queue
package com.itdoc.multi.sync009; import java.util.LinkedList; import java.util.concurrent.TimeUnit; ...
- 百度vue服务端渲染(ssr)有感
前端各种框架工具层次不穷,日新月异,越学越混乱了快 知乎上看到了一段回复,豁然开朗的感觉. Web 2.0时代最大的思想革命本质不是前后端分离,而是把网页当作独立的应用程序(app).前后端分离只是实 ...
- IOS 学习资料整理{非常有用,强烈推荐}
绝地地的资源博客:我是雷锋不用谢~~啦啦啦 https://blog.csdn.net/kunga0814/article/details/82117090
- session超时设置+超时页面跳转
session超时设置,方法有三种: (1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(600);参数600单位是秒,即在没有10分钟活动后,sessio ...
- 【BZOJ2818】Gcd [莫比乌斯反演]
Gcd Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 给定整数N,求1<=x,y&l ...
- C++ 异常~一 转
C++ 异常机制分析 阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexce ...
- 简单粗暴的webapp语言国际化
不同语言以json格式存放不同文件 { "information": "个人资料", "fuckworld":"你好世界" ...
- 【 Zabbix 】— 基础知识
zabbix基础 zabbix是一个高度集成的网络监控套件.通过一个软件包即可提供如下特性: 1.数据收集 (1)可用性及性能检测 (2)支持SNMP.IPMI.JMX监控 (3)自定义检测 (4)自 ...
- 【计算机网络】wireshark抓包分析2
在分析1中,大概的看到了一个包中的信息.这里,看看这些包究竟在做什么 这是我的电脑跟某个网站交互的前4个包. 其中前三个包可以明显看出是TCP的三次握手. 那么,问题来了: 为什么第三个包的长度比前两 ...