4585: [Apio2016]烟火表演

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 100  Solved: 66
[Submit][Status][Discuss]

Description

烟花表演是最引人注目的节日活动之一。在表演中,所有的烟花必须同时爆炸。为了确保安
全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连。导火索的连接方式形成
一棵树,烟花是树叶,如[图1]所示。火花从开关出发,沿导火索移动。每当火花抵达一个分
叉点时,它会扩散到与之相连的所有导火索,继续燃烧。导火索燃烧的速度是一个固定常
数。[图1]展示了六枚烟花{E1,E2...E6 }的连线布局,以及每根导火索的长度。图中还标
注了当在时刻 从开关点燃火花时,每一发烟花的爆炸时间。
Hyunmin为烟花表演设计了导火索的连线布局。不幸的是,在他设计的布局中,烟花不一定
同时爆炸。我们希望修改一些导火索的长度,让所有烟花在同一时刻爆炸。例如,为了让[图
1]中的所有烟花在时刻 13爆炸,我们可以像[图2]中左边那样调整导火索长度。类似地,为
了让[图1]中的所有烟花在时刻 14爆炸,我们可以像[图2]中右边那样调整长度。
修改导火索长度的代价等于修改前后长度之差的绝对值。例如,将[图1]中布局修改为[图2]
左边布局的总代价为6 ,而将[图1]中布局修改为[图2]右边布局的总代价为 5.
导火索的长度可以被减为0 ,同时保持连通性不变。
给定一个导火索的连线布局,你需要编写一个程序,去调整导火索长度,让所有的烟花在同
一时刻爆炸,并使得代价最小。
 

Input

所有的输入均为正整数。令 N代表分叉点的数量, M代表烟花的数量。分叉点从1 到N 编

号,编号为1 的分叉点是开关。烟花从N+1 到 N+M编号。1<=N+M<=300,000
输入格式如下:
N M
P2 C2
P3 C3
...
Pn Cn
PN+1 CN+1
...
PN+m CN+M
其中Pi 满足 1<=Pi<i,代表和分叉点或烟花i 相连的分叉点。 Ci代表连接它们的导火索长
度( 1<=Ci<=10^9)。除开关外,每个分叉点和多于1 条导火索相连,而每发烟花恰好与 1条导
火索相连。

Output

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

Sample Input

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

Sample Output

5

HINT

 

Source

可并堆
  考虑一个点f(x)表示将这个点子树所有叶节点深度变成x的最小代价
  发现是个下凸函数,并且是线性的
  对于一个点,假设f(x=[L,R])取得最小值
  考虑加上到父亲的边权w
    if(x<=L) f(x)=f(x)+w
    if(L<x<=L+w) f(x)=f(L)+w-(x-L)
    if(L+w<x<=R+w) f(x)=f(L)
    if(x>R+w) f(x)=f(L)+x-R-w
  发现实际上是把第一段向上平移,中间加入斜率为-1,0,1的直线
  把多个合并起来,右边的斜率最大值就是其度数
  那么我们考虑它到父亲贡献时,把斜率为正的点都pop掉
  然后暴力添加拐点即可,每次只会加2个
  合并就直接用可并堆了,我写的左偏树
  最后取出1这个点的最小值时,我们是这样计算的
  把斜率>=0的都pop掉,提取1-L的所有点
  f(0)=∑树边权,然后斜率每次-1直到0
  那么从右往左减就可以了
  sum-=p[i]可以理解为把p[i]的斜率=-1的贡献算进去,然后前面所有直线斜率-=1
  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<iostream>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N=6e5+;
  7. char *buf=(char *)malloc(<<),*is=buf,*it=buf;
  8. #define getc() (is==it&&(it=(is=buf)+fread(buf,1,1<<15,stdin),is==it)?0:*is++)
  9. ll sum,v[N];
  10. int n,m,fa[N],son[N],dis[N];int tot,rt[N],l[N],r[N];
  11. inline void read(int &x){
  12. int f=;x=;char ch=getc();
  13. while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
  14. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
  15. x*=f;
  16. }
  17. int merge(int x,int y){
  18. if(!x||!y) return x+y;
  19. if(v[x]<v[y]) swap(x,y);
  20. r[x]=merge(r[x],y);
  21. swap(l[x],r[x]);
  22. return x;
  23. }
  24. inline int pop(int x){
  25. return merge(l[x],r[x]);
  26. }
  27. void dfs(int x){
  28. if(!x) return ;
  29. sum-=v[x];
  30. dfs(l[x]);
  31. dfs(r[x]);
  32. }
  33. int main(){
  34. read(n);read(m);
  35. for(int i=,x,y;i<=n+m;i++){
  36. read(fa[i]);read(dis[i]);
  37. son[fa[i]]++;sum+=dis[i];
  38. }
  39. for(int i=n+m;i>;i--){
  40. ll L=,R=;
  41. if(son[i]){
  42. while(--son[i]) rt[i]=pop(rt[i]);
  43. R=v[rt[i]];rt[i]=pop(rt[i]);
  44. L=v[rt[i]];rt[i]=pop(rt[i]);
  45. }
  46. v[++tot]=L+dis[i];
  47. v[++tot]=R+dis[i];
  48. rt[i]=merge(rt[i],merge(tot-,tot));
  49. rt[fa[i]]=merge(rt[fa[i]],rt[i]);
  50. }
  51. while(son[]--) rt[]=pop(rt[]);
  52. dfs(rt[]);
  53. cout<<sum;
  54. return ;
  55. }

【APIO2016】Fireworks[DP 可并堆维护凸包优化]的更多相关文章

  1. [UOJ#268]. 【清华集训2016】数据交互[动态dp+可删堆维护最长链]

    题意 给出 \(n\) 个点的树,每个时刻可能出现一条路径 \(A_i\) 或者之前出现的某条路径 \(A_i\) 消失,每条路径有一个权值,求出在每个时刻过后能够找到的权值最大的路径(指所有和该路径 ...

  2. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  3. BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)

    BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...

  4. UOJ268 [清华集训2016] 数据交互 【动态DP】【堆】【树链剖分】【线段树】

    题目分析: 不难发现可以用动态DP做. 题目相当于是要我求一条路径,所有与路径有交的链的代价加入进去,要求代价最大. 我们把链的代价分成两个部分:一部分将代价加入$LCA$之中,用$g$数组保存:另一 ...

  5. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  6. 懒人的福利?教你用set维护斜率优化凸包

    斜率优化题目大家肯定都做得不少了,有一些题目查询插入点的x坐标和查询斜率都不单调,这样就需要维护动态凸包并二分斜率.(例如bzoj1492) 常规的做法是cdq分治或手写平衡树维护凸包,然而如果我不愿 ...

  7. 【CF932F】Escape Through Leaf 启发式合并set维护凸包

    [CF932F]Escape Through Leaf 题意:给你一棵n个点的树,每个点有树形ai和bi,如果x是y的祖先,则你可以从x花费$a_x\times b_y$的费用走到y(费用可以为负). ...

  8. 【BZOJ2300】[HAOI2011]防线修建 set维护凸包

    [BZOJ2300][HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可 ...

  9. 【bzoj3533】[Sdoi2014]向量集 线段树+STL-vector维护凸包

    题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...

随机推荐

  1. 最简单的基于FFmpeg的移动端样例:Android 视频解码器-单个库版

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  2. mongo 内存限制wiredTigerCacheSizeGB = 10

    [root@iZ2zed126f44v90yv59ht3Z rabbitmq]# cat /usr/local/mongodb/mongodb.confport = 27017dbpath = /us ...

  3. Python 字符串切片

    #-*- coding:utf-8 -*- #字符串切片 names = "abcdefgh" ''' 切片语法 names[起始位置:终止位置:步长] 起始位置:即字符串的下标, ...

  4. thinkphp 3.2

    ---恢复内容开始--- http://url.cn/ejCVUQ ---恢复内容结束---

  5. nodejs基础 -- NPM 使用介绍

    npm:是nodejs的包管理工具,随NodeJS一起安装的,能解决NodeJS代码部署上的很多问题,如: 1.允许用户从NPM服务器下载别人编写的第三方包到本地使用. 2.允许用户从NPM服务器下载 ...

  6. 利用circpedia 数据库探究circRNA的可变剪切

    circpedia 中收录了利用circexplorer 软件识别到的circRNA, 覆盖了人,小鼠,鸟类,昆虫多个物种的多种细胞系的数据 官网链接如下: http://www.picb.ac.cn ...

  7. 【Java面试题】20 运行时异常和一般异常有何区别

    Throwable 是所有 Java 程序中错误处理的父类 ,有两种资类: Error 和 Exception . Error :表示由 JVM 所侦测到的无法预期的错误,由于这是属于 JVM 层次的 ...

  8. iotop详解

    有时我们希望知道到底哪个进程产生了IO,这个时候就需要iotop这个工具了.它的输出和top命令类似,简单直观.官网:http://guichaz.free.fr/iotop/需要Python 2.5 ...

  9. VCL 中的 Windows API 函数(6): BeginDeferWindowPos

    BeginDeferWindowPos 和 DeferWindowPos.EndDeferWindowPos 是一组一起使用的函数, 可对一组窗口的位置.大小.Z 序等进行调整, 在 ExtCtrls ...

  10. bootstrap中如何使input中的小图标获得点击事件

    bootstrap中,放入input中的小图标是不能点击的. 在表单中经常遇见密码旁边的眼睛图标点击后,可使密码可见. 要使小图标获得点击事件,可在小图标上覆盖一个跟小图标一样大的透明层,然后给透明层 ...