题解

这个听起来很毒瘤的想法写起来却非常休闲,理解起来可能很费劲

例如,我们首先到猜到答案是个下凸包

然后是不是要三分???然而并不是orz

我们通过归纳证明这个下凸包的结论来总结出了一个算法

也就是对于每个子树是一个凸包,我们进行两种操作,一种操作是我给这个子树加了一个父亲边

另一种操作是对所有儿子合并这个凸包

容易发现这两种操作都不会影响答案的下凸性

我们考虑操作1

凸包最小值有一段区间是\([L,R]\)

分类讨论加一条边的情况

\(f(x) = f(x) + w (x <= L)\)也就是在\(L\)之前的要想达到必须全删掉新加的边才是最优的

\(f(x) = f(L) + w - (x - L) (L <= x <= L + w)\)直接从L转移即可

\(f(x) = f(L)(L + w <= x <= R + w)\) 直接平移就是最优的了

\(f(x) = f(R) + w + (x - R)\)从\(R\)转移即可

事实上,这是给凸包下面扯开,加了-1,0,1的三段

由此可一归纳出来,这个凸包斜率变化范围不是很大,自底向上是

-1,0,1和-1,0,1两个卷积

然后依次变大

事实上只要维护每次多的两个拐点就可以,给拐点排序后,删掉斜率为正的部分,最后从最靠上的部分开始往下减

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 300005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M;
int fa[MAXN],C[MAXN],d[MAXN];
int64 sum,p[MAXN * 2];
struct node {
int lc,rc,dis;
int64 v;
}tr[MAXN * 2];
int tot,rt[MAXN],cnt;
int Merge(int x,int y) {
if(!x) return y;
if(!y) return x;
if(tr[x].v < tr[y].v) swap(x,y);
tr[x].rc = Merge(tr[x].rc,y);
if(tr[tr[x].rc].dis > tr[tr[x].lc].dis) swap(tr[x].lc,tr[x].rc);
tr[x].dis = tr[tr[x].lc].dis + 1;
return x;
}
int upt(int x) {return Merge(tr[x].lc,tr[x].rc);}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(N);read(M);
for(int i = 2 ; i <= N + M ; ++i) {
read(fa[i]);read(C[i]);
d[fa[i]]++;
sum += C[i];
}
for(int i = N + M ; i > 1 ; --i) {
int64 l = 0,r = 0;
if(i <= N) {
for(int j = 1 ; j < d[i] ; ++j) rt[i] = upt(rt[i]);
l = tr[rt[i]].v;rt[i] = upt(rt[i]);
r = tr[rt[i]].v;rt[i] = upt(rt[i]);
}
l += C[i];r += C[i];
tr[++tot].v = l;tr[++tot].v = r;
rt[i] = Merge(rt[i],Merge(tot,tot - 1));
rt[fa[i]] = Merge(rt[fa[i]],rt[i]);
}
for(int j = 1 ; j <= d[1]; ++j) rt[1] = upt(rt[1]);
while(rt[1]) {
p[++cnt] = tr[rt[1]].v;
rt[1] = upt(rt[1]);
} for(int i = cnt ; i >= 1 ; --i) {
sum -= p[i];
}
out(sum);enter;
}

【LOJ】#2568. 「APIO2016」烟花表演的更多相关文章

  1. Loj #2568. 「APIO2016」烟花表演

    Loj #2568. 「APIO2016」烟花表演 题目描述 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连 ...

  2. 「APIO2016」烟花表演

    「APIO2016」烟花表演 解题思路 又是一道 solpe trick 题,观察出图像变化后不找一些性质还是挺难做的. 首先令 \(dp[u][i]\) 为节点 \(u\) 极其子树所有叶子到 \( ...

  3. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  4. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  5. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  6. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  7. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  8. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

  9. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

随机推荐

  1. 洛谷P1155 双栈排序

    这题什么毒瘤......之前看一直没思路,然后心说写个暴搜看能有多少分,然后就A了??! 题意:给你一个n排列,求它们能不能通过双栈来完成排序.如果能输出最小字典序方案. [update]这里面加了一 ...

  2. 界面编程之QT的Socket通信20180730

    /*******************************************************************************************/ 一.linu ...

  3. gulp入门教程(转)

    一.gulp简介     1.gulp是什么? gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器:它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自 ...

  4. 构造代码块----java基础总结

    前言:之前一直不知道构造代码块的意思是什么,只是知道他的具体的表现形式,因为经常在面试题中看到,所以准备好好写写. 作用: 给对象进行初始化,对象一建立就运行,而且优于构造方法运行. 和构造方法的区别 ...

  5. python爬虫 抓取一个网站的所有网址链接

    sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campai ...

  6. python---django中orm的使用(2)

    1.基于对象的正向查询和反向查询 在python---django中orm的使用(1)中也提到了正向和反向查找 表:一对多  书籍和出版社 class Book(models.Model): titl ...

  7. Kafka 温故(一):Kafka背景及架构介绍

    一.Kafka简介 Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,使用Scala语言编写,之后成为Apache项目的一部分.Kafka是一个分布式的,可划分的,多订阅者,冗余 ...

  8. 【原创】when.js2.7.1源码解析

    现在,用回调处理一些复杂的逻辑,显得代码臃肿,难于阅读,特别是异步,嵌套. 解决这样的问题,可以是之前所说的Backbone.Events的pubsub,或者是今天要说的when.js所实现的prom ...

  9. 数链剖分(Tree)

    题目链接:https://cn.vjudge.net/contest/279350#problem/D 题目大意:操作,单点查询,区间取反,询问区间最大值. AC代码: #include<ios ...

  10. parallelogram

    The parallelogram law in inner product spaces Vectors involved in the parallelogram law. In a normed ...