[APIO2016]烟火表演
题目描述
https://www.lydsy.com/JudgeOnline/problem.php?id=4585
题解
这题太神了。
我们可以先列出一个dp方程,dp[x][d]表示x节点到所有叶子的距离的d时的代价。
结论1:对于每个点来说,这个dp数组为二维平面上是一个下凸函数。
证明:对于叶子来说一定成立,在w[x]处为0,然后小于w[x]的部分斜率为-1,大与w[x]的部斜率为1。
对于非叶子节点 ,它的函数时有儿子们加起来的,也成立。
然后我们考虑一个点如何向父亲转移。
这是要分四种情况,假设当前节点的斜率为0的部分为L~R。
x<=L f'(x)=f(x)+w[u]
因为边权不能为负,所以我们只能从小的地方往大的地方转移。

比如这个蓝点,它只能从它以及前面的地方转移,但从自己转移时最优的。
x>=L&&x<=L=w[u] f'(x)=f(L)+w-(x-L)
在L处答案为f(L)+w,没往右动一格代价会-1。
x>=L+w[u]&&x<=R+w[u] f'(x)=f(L)
这个相当于直接转移了,没有代价。
x>=R+w[u] f'(x)=f(x)+(x-R)-w
相当于是走过了,会产生代价。
我们发现转移大概长这样(继续盗图)。

我们把左边的点向上动一段后插入斜率为-1的线,再把斜率为0的部分向右平移,最后面是斜率为1的线。
然后这种操作就可以维护了。
思路大概就是只维护拐点,用一个可并堆,每次把右边的部分弹掉。
结论2:每次合并到一个非叶子节点时,斜率为0的线右边有n个点,n为该点的儿子数。
证明:因为最后那一块斜率一定为n(n个斜率为1的直线相加),然后往前经过一个拐点,斜率会-1。
然后把LR取出来做平移,再插回去,最后一直合并到1。
结论3:每经过一个拐点,斜率-1(其实它和上面的结论一个意思)。
然后就可以利用最后的拐点直接算答案了。
怎么算呢?我们把斜率>=0的直线弹掉,把前面的所有直线斜率+1,那么每条直线都会产生deltax的代价,总共有xn的代价,那我们就在答案里+xn,此时最后一条直线斜率为0,把它删掉。
然后一直做,最后得到的是f(0)-f(min),f(0)就是所有边权之和,那么f(min)就可以求出来了。
代码
#include<iostream>
#include<cstdio>
#define N 600002
using namespace std;
typedef long long ll;
int deep[N],d[N],n,m,fa[N],T[N],tot;
ll sum,w[N];
inline ll rd(){
ll x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct tr{
ll v;int l,r;
}tr[N];
int merge(int x,int y){
if(!x||!y)return x^y;
if(tr[x].v<tr[y].v)swap(x,y);
tr[x].r=merge(tr[x].r,y);
if(deep[tr[x].l]<deep[tr[x].r])swap(tr[x].l,tr[x].r);
deep[x]=deep[tr[x].r]+;
return x;
}
inline int pop(int x){return merge(tr[x].l,tr[x].r);}
int main(){
n=rd();m=rd();
for(int i=;i<=n+m;++i){
fa[i]=rd();w[i]=rd();sum+=w[i];d[fa[i]]++;
}
for(int i=n+m;i>=;--i){
ll l=,r=;
if(i<=n){
while(--d[i])T[i]=pop(T[i]);
l=tr[T[i]].v;T[i]=pop(T[i]);
r=tr[T[i]].v;T[i]=pop(T[i]);
}
tr[++tot].v=l+w[i];tr[++tot].v=r+w[i];
T[i]=merge(T[i],merge(tot-,tot));
T[fa[i]]=merge(T[fa[i]],T[i]);
}
while(d[]--)T[]=pop(T[]);
while(T[]){sum-=tr[T[]].v;T[]=pop(T[]);}
cout<<sum;
return ;
}
[APIO2016]烟火表演的更多相关文章
- bzoj 4585: [Apio2016]烟火表演【左偏树】
参考:https://blog.csdn.net/wxh010910/article/details/55806735 以下课件,可并堆部分写的左偏树 #include<iostream> ...
- 洛谷P3642 [APIO2016]烟火表演
传送门 题解 fy大佬好强……我根本看不懂…… //minamoto #include<bits/stdc++.h> #define ll long long using namespac ...
- 【APIO2016】烟火表演
题面 题解 神仙题目啊QwQ 设\(f_i(x)\)表示以第\(i\)个点为根的子树需要\(x\)秒引爆的代价. 我们发现,这个函数是一个下凸的一次分段函数. 考虑这个函数合并到父亲节点时会发生怎样的 ...
- bzoj 4585 烟火表演 - 动态规划 - 可并堆
题目传送门 传送门I 传送门II 题目大意 给定一棵带边权有根树,修改一条边的边权的代价是修改前和修改后的值的绝对值之差.不能将一条边的边权改为负数.问使得根节点到所有叶节点的距离相等的最小代价. 当 ...
- 【APIO2016】Fireworks[DP 可并堆维护凸包优化]
4585: [Apio2016]烟火表演 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 100 Solved: 66[Submit][Status] ...
- UOJ #205/BZOJ 4585 【APIO2016】Fireworks 可并堆+凸包优化Dp
4585: [Apio2016]烟火表演 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 115 Solved: 79[Submit][Status] ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- test20190909 Gluttony
0+0+0+0+0+0=0.毒瘤出题人. BJOI2019 勘破神机 地灾军团的军师黑袍从潜伏在精灵高层的密探手中得知了神杖的情报,他对奥术宝石中蕴含的远古神秘力量十分感兴趣.他设计夺取了数块奥术宝石 ...
- [笔记] Slope Trick:解决一类凸代价函数的DP优化问题
原理 当序列 DP 的转移代价函数满足 连续: 凸函数: 分段线性函数. 时,可以通过记录分段函数的最右一段 \(f_r(x)\) 以及其分段点 \(L\) 实现快速维护代价的效果. 如:$ f(x) ...
随机推荐
- 【问题解决方案】之 jmeter启动报错:Not able to find Java executable or version. Please check your Java installation
故事发生在云计算实验课上-- ** 故事发生在云计算实验课上-- Step 1 在Xshell中登录自己的cloud虚拟机后,<sudo su ->切换到root用户 Step 2 < ...
- 容错处理try
var num = 90; try{ console.log( num + 100 ); consolel.log(aaa); }catch(e){ console.log("如果程序中有异 ...
- JSON for-in 遍历
(代码均以js代码示例) 1.可以使用 for-in 来循环对象的属性,使用中括号([])来访问属性的值: 这中方法便于一些在不确定有属性的情况下使用. var myObj = { "nam ...
- 在Laravel中使用数据库事务以及捕获事务失败后的异常
Description 在Laravel中要想在数据库事务中运行一组操作,则可以在 DB facade 中使用 transaction 方法.如果在事务的闭包内抛出异常,事务将会被自动还原.如果闭包运 ...
- 解决方法:CentOS7用yum安装软件显示错误:cannot find a valid baseurl for repo: base/7/x86_64
在Linux学习中,发现使用yum安装软件出现以下的错误: 百度了各种方法,很多人也发现光是修改REBOOT=yes也没用,多次进行挂载.修改网卡配置文件.重置IP地址.重启网络.创建又删除配置文件的 ...
- Struts2——namespace、action、以及path问题
简单的介绍下Struts2中的几个简单的问题(namespace.action.以及path问题) namespace(命名空间) Namespace决定了action的访问路径,默认为“”,意味着可 ...
- dom 事件主要内容
一 . onclick(单击) 原图 单击btn1 在点击btn2 二 . onfocus 和 onblur onfocus(聚焦, 鼠标点击输入框) onblur(模糊, 鼠标点击输入框外的地方) ...
- Gatsby & React & NPX & NVM
Gatsby & React Gatsby is a blazing fast modern site generator for React. https://www.gatsbyjs.or ...
- 创建简单的表单Demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue实例相关
第一种方法要比第二种更省事 if (!row.alert_at) return; if(row.alert_at){ } else { } v-for="todo in list" ...