题目描述

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. [转帖] 百度知道: KMS 和OSPP

    https://zhidao.baidu.com/question/1819332749671662308.html Key Management Service (KMS).目前Windows Se ...

  2. [转帖]NotePad++编辑Linux中的文件

    NotePad++编辑Linux中的文件 https://blog.csdn.net/chengqiuming/article/details/78882692 原作者 未经允许不允许转帖 加密自己参 ...

  3. C# Note34: 异常机制相关小点

    1.使用throw和throw ex抛出异常的区别 通常,我们使用try/catch/finally语句块来捕获异常,那么在抛出异常的时候,使用throw和throw ex有什么区别呢? 假如,按顺序 ...

  4. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

    今天服务器遇到了一个很熟悉的问题, 输入 #mysql -u root -p   ERROR 2002 (HY000):Can't connect to local MySQL server     ...

  5. Mybatis核心配置文件SqlMapConfig.xml

    配置内容: SqlMapConfig.xml中配置的内容和顺序如下: 1.properties(属性) 2.settings(全局配置参数) 3.typeAliases(类型别名) 4.typeHan ...

  6. uname -r查询版本不是安装的版本的问题

    uname -r 查出来的版本与/lib/modules下面的内核版本不匹配.啥原因? 第一步,先strace uname -r看看这个uname -r到底从哪里获取的版本. strace没有看出来 ...

  7. jedis集群版应用

    1.pom文件添加依赖: 2.创建配置文件 <!-- jedis集群版配置(JedisCluster通过构造传参(2个参数)) --> <bean id="redisCli ...

  8. DOSD用scratch的方式训练通用目标检测,性能很高

    推荐一篇今年ICCV上基于DenseNet的general object detection的工作.这是目前已知的第一篇在完全脱离ImageNet pre-train模型的情况下使用deep mode ...

  9. u盘中毒,启动显示找不到指定模块

    u盘中毒,插入电脑,启动显示找不到指定模块,关闭杀毒软件还是这样: 小编经常是在学校教室的电脑上插入U盘再拔出就出现这样的情况,遇到N次了, 所以决定把方法记录下来: (演示使用的是win10系统,其 ...

  10. 使用Google ZXing生成和解析二维码

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...