洛谷传送门

BZOJ传送门

题目描述

烟花表演是最引人注目的节日活动之一。在表演中,所有的烟花必须同时爆炸。为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连。导火索的连接方式形成一棵树,烟花是树叶,如图所示。火花从开关出发,沿导火索移动。每当火花抵达一个分叉点时,它会扩散到与之相连的所有导火索,继续燃烧。导火索燃烧的速度是一个固定常数。图中展示了六枚烟花 {E1,E2,…,E6}{E1,E2,…,E6}\{E_1, E_2, \dots, E_6\} 的连线布局,以及每根导火索的长度。图中还标注了当在时刻 000 从开关点燃火花时,每一发烟花的爆炸时间。

Hyunmin 为烟花表演设计了导火索的连线布局。不幸的是,在他设计的布局中,烟花不一定同时爆炸。我们希望修改一些导火索的长度,让所有烟花在同一时刻爆炸。例如,为了让图中的所有烟花在时刻 13" role="presentation" style="position: relative;">131313 爆炸,我们可以像下图中左边那样调整导火索长度。类似地,为了让图中的所有烟花在时刻 141414 爆炸,我们可以像下图中右边那样调整长度。

修改导火索长度的代价等于修改前后长度之差的绝对值。例如,将上面那副图中布局修改为下面那副图的左边布局的总代价为 666 ,而修改为右边布局的总代价为 5" role="presentation" style="position: relative;">555 。

导火索的长度可以被减为 000 ,同时保持连通性不变。

给定一个导火索的连线布局,你需要编写一个程序,去调整导火索长度,让所有的烟花在同一时刻爆炸,并使得代价最小。

输入输出格式

输入格式:

所有的输入均为正整数。令 N" role="presentation" style="position: relative;">NNN 代表分叉点的数量, MMM 代表烟花的数量。分叉点从 1" role="presentation" style="position: relative;">111 到 NNN 编号,编号为 1" role="presentation" style="position: relative;">111 的分叉点是开关。烟花从 N+1N+1N + 1 到 N+MN+MN + M 编号。

输入第一行为 N,MN,MN, M。后面 N+M−1N+M−1N + M - 1 行,第 iii 行两个整数 Pi+1,Ci+1" role="presentation" style="position: relative;">Pi+1,Ci+1Pi+1,Ci+1P_{i + 1}, C_{i + 1} 。其中 PiPiP_i 满足 1≤Pi<i1≤Pi<i1 \leq P_i ,代表和分叉点或烟花 iii 相连的分叉点。 Ci" role="presentation" style="position: relative;">CiCiC_i 代表连接它们的导火索长度( 1≤Ci≤1091≤Ci≤1091 \leq C_i \leq 10^9 )除开关外,每个分叉点和多于 111 条导火索相连,而每发烟花恰好与 1" role="presentation" style="position: relative;">111 条导火索相连。

输出格式:

输出调整导火索长度,让所有烟花同时爆炸,所需要的最小代价。

输入输出样例

输入样例#1:

4 6
1 5
2 5
2 8
3 3
3 2
3 3
2 9
4 4
4 3

输出样例#1:

5

说明

【数据规模】

子任务 1(7 分): N=1N=1N = 1,1≤M≤1001≤M≤1001 \leq M \leq 100 。

子任务 2(19 分): 1≤M≤3001≤M≤3001 \leq M \leq 300 ,且开关到任一烟花的距离不超过 300300300 。

子任务 3(29 分): 1≤M≤50001≤M≤50001 \leq M \leq 5000 。

子任务 4(45 分): 1≤M≤3000001≤M≤3000001 \leq M \leq 300000 。

解题分析

神题啊QAQ蒟蒻搞了好久才弄明白…

首先我们考虑fA(x)fA(x)f_A(x)表示将AAA点子树内所有烟火爆炸时间变为x" role="presentation" style="position: relative;">xxx的花费,显然这是个下凸的函数,并且fA(0)=∑leafi∈subtree[A]dis[i]fA(0)=∑leafi∈subtree[A]dis[i]f_A(0)=\sum _{leaf_i\in subtree[A]}dis[i]。

然后我们考虑从fA(x)fA(x)f_A(x)转移到ffat[A](x)ffat[A](x)f_{fat[A]}(x)的过程。设[L,R][L,R][L,R]为f(x)f(x)f(x)上最低的一段,dis[A]dis[A]dis[A]为A→fat[A]A→fat[A]A\to fat[A]的长度,f′A(x)fA′(x)f_A'(x)为转移后的函数。

  • 对于x∈[0,L]x∈[0,L]x\in [0,L],显然我们要将新的导火索清零, 所以这一段函数向上平移dis[A]dis[A]dis[A],即f′A(x)=fA(x)+dis[A]fA′(x)=fA(x)+dis[A]f_A'(x)=f_A(x)+dis[A]。
  • 对于x∈[L+1,L+dis[A]−1]x∈[L+1,L+dis[A]−1]x\in [L+1,L+dis[A]-1],我们可以不修改以前的导火索,只减短新的导火索的长度。f′A(x)=fA(x)+dis[A]−(x−L)fA′(x)=fA(x)+dis[A]−(x−L)f'_A(x)=f_A(x)+dis[A]-(x-L)。
  • 对于x∈[L+dis[A],R+dis[A]]x∈[L+dis[A],R+dis[A]]x\in [L+dis[A],R+dis[A]],这一截就是原来的[L,R][L,R][L,R]转移过来的,所以f′A(x)=fA(L)fA′(x)=fA(L)f'_A(x)=f_A(L)。
  • 对于x∈[R+dis[A]+1,+∞)x∈[R+dis[A]+1,+∞)x\in [R+dis[A]+1,+∞),我们可以加长新的导火索的长度,所以f′A(x)=fA(R)+x−(R+dis[A])fA′(x)=fA(R)+x−(R+dis[A])f'_A(x)=f_A(R)+x-(R+dis[A])

也就是说大概是这个样子(dis[A]=2的情况):

可以发现其实就是把fA(x)fA(x)f_A(x)斜率非负的一半砍掉,另一半向上平移, 再加入斜率为−1,0,1−1,0,1-1,0,1的三段直线。

考虑如何合并几个凸包的f′(x)f′(x)f'(x)从而得到ffat[A](x)ffat[A](x)f_{fat[A]}(x)。大概就像下面这样:

然后我们可以发现,对于合并后的凸包,每个原来的节点都会使斜率+1+1+1(其实上图的A→B→C→D→EA→B→C→D→EA\to B \to C\to D\to E这个凸包的BBB点少画了一个重合的点)。所以我们用一个可并堆直接暴力合并子树中的凸包。

那么如何得到合并后凸包的最小值?我们可以发现合并后的凸包的斜率为正部分的点数就是子树的个数,所以直接弹出son[fat[A]]" role="presentation" style="position: relative;">son[fat[A]]son[fat[A]]son[fat[A]]次即可。

但这样处理后我们只得到了[L,R][L,R][L,R]区间,并没有得到对应的花费。这时有一个更妙妙的性质:因为每个点都会使凸包斜率+1,所以考虑一个在xixix_i位置的点,其对花费的贡献是−xi−xi-x_i,所以我们一边弹堆一边用总路径和(即为f1(x)f1(x)f_1(x))减去堆顶的元素。

(如果还有不太懂的同学可以画画图演示,博主反正是画图才懂QAQ)

下面是极其简短的代码(pb_ds大法好

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ext/pb_ds/priority_queue.hpp>
#define R register
#define IN inline
#define gc getchar()
#define W while
#define MX 300050
#define ll long long
template <class T>
IN void in(T &x)
{x = 0; R char c = gc;W (!isdigit(c)) c = gc;W (isdigit(c))x = (x << 1) + (x << 3) + c - 48, c = gc;
}
__gnu_pbds::priority_queue <ll> que[MX];
int son[MX], fat[MX], dis[MX], rop, fir;
ll sum;
int main(void)
{ll lef, rig;in(rop), in(fir); int bd = rop + fir;for (R int i = 2; i <= bd; ++i){in(fat[i]), in(dis[i]);son[fat[i]]++; sum += dis[i];}for (R int i = bd; i >= 2; --i){lef = rig = 0;if(i <= rop){W (--son[i]) que[i].pop();lef = que[i].top(), que[i].pop();rig = que[i].top(), que[i].pop();}que[i].push(lef + dis[i]), que[i].push(rig + dis[i]);que[fat[i]].join(que[i]);//配对堆骚操作,直接合并}W (son[1]--) que[1].pop();W (!que[1].empty()) sum -= que[1].top(), que[1].pop();printf("%lld", sum);
}

[Luogu P3642] [BZOJ 4585] [APIO2016]烟火表演相关推荐

  1. luogu P3642 [APIO2016]烟火表演

    https://www.luogu.com.cn/problem/P3642 好毒瘤啊!!! 首先按照套路 设f(x)表示以u为根的,距离为x的最小代价设f(x)表示以u为根的,距离为x的最小代价设f ...

  2. P3642 [APIO2016]烟火表演(左偏树、函数)

    解析 感觉是左偏树的神题了. 首先有一个比较显然的结论,一个合法的方案中,两个叶子到它们 lca\text{lca}lca 的距离必须相等. 考虑设计 dp\text{dp}dp : fi,xf_{i ...

  3. [APIO2016]烟火表演

    链接:https://www.luogu.org/problemnew/show/P3642 跟上一道题类似但更难,首先也是观察出在某个节点代价是下凸的函数,并且得到转移方程: 1.x<=L f ...

  4. BZOJ4585: [Apio2016]烟火表演

    Description 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安 全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连.导火索的连接方式形成 一棵树,烟花 ...

  5. 【LOJ】apio2016烟火表演-可并堆凸包

    讲解详见ppt%%%% 代码 #include<cstdio> #include<cstring> #include<iostream> #include<a ...

  6. BZOJ4585 [Apio2016]烟火表演

    "这个凸包的形式,妙啊,他妙啊,妙啊" 王梦迪神犇在讲题的时候写的题解挺详细的 我们对每个点,有一个把子树内长度统一的花费关于统一成的长度的函数f(x),易知这个函数是下凸的,对于 ...

  7. Luogu P1198 BZOJ 1012 最大数 (线段树)

    Luogu P1198 BZOJ 1012 最大数 (线段树) 手动博客搬家: 本文发表于20170821 14:32:05, 原地址https://blog.csdn.net/suncongbo/a ...

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

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

  9. 【APIO2016】烟火表演(可并堆)(折线DP)

    传送门 题解: 设fi(x)f_i(x)fi​(x)表示在iii的子树中,所有叶子到iii距离为xxx的时候,子树内部修改的最小代价. 显然是个分段一次函数,大力讨论记录下端点就行了. 注意到可能会出 ...

最新文章

  1. 走近webpack(0)--正文之前的故事
  2. linux学习(3) 关机使命
  3. 设计模式--代理(Proxy)模式
  4. LVS NAT 模型配置实例
  5. LeetCode数据库 176. 第二高的薪水
  6. python竞赛试题及答案_【技术分享】用python解NOIP竞赛题
  7. 零基础学python图文版-教到你会为止的Python入门课程即将开班
  8. 广西计算机一级机试考试试题,2010年12月广西区计算机一级考试机试试题
  9. C语言 库函数:qsort 详解
  10. html点击图片可以放全屏,html:点击图片放大到全屏,再次点击缩回
  11. 合宙Air720UH链接阿里云流程
  12. 职场思想分享009 | 一个人对待工作的态度决定其成绩的多少?
  13. MVC简介——一篇非常简单易懂的介绍
  14. 小白必学的Ps火焰字制作教程
  15. 评价神经网络性能的指标,神经网络是参数模型吗
  16. python wx包_今天玩点啥:python真香系列之利用wxpy包写一个微信消息自动回复插件...
  17. 【C++】(一)C++入门第一课
  18. 什么是大小端,如何写程序判断大小端?
  19. 求两个正整数的最大公约数和最小公倍数
  20. 今天,想和姐妹们聊聊技术与成长|大厂程序媛的升级打怪之路

热门文章

  1. 如何实现网站事件统计与事件分析
  2. php中文网教程 百度云,网盘直链问题请教
  3. 基于FME实现等高线的计曲线连接工具,快速连接计曲线在计曲线注记点断开处的缺口,计曲线批量连接,等高线批量连接
  4. 如何自己动手为家庭做一套安防监控系统
  5. java点餐系统实验报告_JAVA课程实践报告 基于web的点餐系统毕业设计.doc
  6. PS2020一打开就闪退的解决办法
  7. python数据分析案例分析题_Python数据分析-案例分析
  8. 静态成员和非静态成员的区别
  9. 数据库的入门简单了解
  10. [opencv入门]1.2.6像素处理RGB三颜色数组图