题目描述

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]烟火表演的更多相关文章

  1. bzoj 4585: [Apio2016]烟火表演【左偏树】

    参考:https://blog.csdn.net/wxh010910/article/details/55806735 以下课件,可并堆部分写的左偏树 #include<iostream> ...

  2. 洛谷P3642 [APIO2016]烟火表演

    传送门 题解 fy大佬好强……我根本看不懂…… //minamoto #include<bits/stdc++.h> #define ll long long using namespac ...

  3. 【APIO2016】烟火表演

    题面 题解 神仙题目啊QwQ 设\(f_i(x)\)表示以第\(i\)个点为根的子树需要\(x\)秒引爆的代价. 我们发现,这个函数是一个下凸的一次分段函数. 考虑这个函数合并到父亲节点时会发生怎样的 ...

  4. bzoj 4585 烟火表演 - 动态规划 - 可并堆

    题目传送门 传送门I 传送门II 题目大意 给定一棵带边权有根树,修改一条边的边权的代价是修改前和修改后的值的绝对值之差.不能将一条边的边权改为负数.问使得根节点到所有叶节点的距离相等的最小代价. 当 ...

  5. 【APIO2016】Fireworks[DP 可并堆维护凸包优化]

    4585: [Apio2016]烟火表演 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 100  Solved: 66[Submit][Status] ...

  6. UOJ #205/BZOJ 4585 【APIO2016】Fireworks 可并堆+凸包优化Dp

    4585: [Apio2016]烟火表演 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 115  Solved: 79[Submit][Status] ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. test20190909 Gluttony

    0+0+0+0+0+0=0.毒瘤出题人. BJOI2019 勘破神机 地灾军团的军师黑袍从潜伏在精灵高层的密探手中得知了神杖的情报,他对奥术宝石中蕴含的远古神秘力量十分感兴趣.他设计夺取了数块奥术宝石 ...

  9. [笔记] Slope Trick:解决一类凸代价函数的DP优化问题

    原理 当序列 DP 的转移代价函数满足 连续: 凸函数: 分段线性函数. 时,可以通过记录分段函数的最右一段 \(f_r(x)\) 以及其分段点 \(L\) 实现快速维护代价的效果. 如:$ f(x) ...

随机推荐

  1. Java Core - Class文件结构之魔数、版本号、常量池

    下图是一个.java文件被编译器编译后产生的二进制的class文件的内容:由图可知,class文件是用两位16进制数来表示的一个字节. 1个字节就是1Byte,1Byte=8bit. 一.魔数(CAF ...

  2. Satis搭建composer私有库(自定义下载目录)

    在我们的日常php开发中需要使用大量的第三方包和类库, 怎么管理是一个问题, 我们用的Yii2框架, 但是并没有把composer用起来, 由于最近更换为docker部署项目, 于是想起来用compo ...

  3. [服务器]Gartner:2018年第四季度全球服务器收入增长17.8% 出货量增长8.5%

    Gartner:2018年第四季度全球服务器收入增长17.8% 出货量增长8.5% Gartner 是不是也是花钱买榜的主啊.. 简单看了一下 浪潮2018Q4的营收18亿刀 (季度营收110亿人民币 ...

  4. UTC时间、GMT时间、本地时间、Unix时间戳

    引用: https://blog.csdn.net/u012102306/article/details/51538574 https://blog.csdn.net/foxir/article/de ...

  5. K3CLOUD数据权限授权

    1.定义角色,把用户放入角色内 2.设置数据规则 3.设置业务对象功能授权

  6. python之路-列表、元组、range

    一 . 列表 # 列表的定义 列表就是能装对象的对象 在python中用[ ]来描述列表,内部元素用逗号隔开,对数据类型没有要求 索引和切片 lst = ["天龙八部", &quo ...

  7. python学习笔记(3)--turtle简单绘制

    参考:大学生mooc 北京理工大学的python程序与设计课程 蟒蛇绘制代码如下: #pythonDraw.py import turtle turtle.setup(650,350,200,200) ...

  8. MySQL中and和or的优先级的问题

    参考资料: 关于MySQL中AND和OR的优先级的问题 SQL语句中的AND和OR执行顺序问题 MySQL带OR关键字的多条件查询

  9. UML符号

    转抄, 语言简练. 挺好. -------------------  -------------------  -------------------  -------------------  -- ...

  10. QTP 自动货测试桌面程序-笔记-运行结果中添加截图

    3种方法: 方法1:使用设置:SnapshotReportMode oldMode = Setting("SnapshotReportMode") Setting("Sn ...