APIO2016 烟火表演
给定一棵树,带边权。
写出转移方程。
其中
引理:
证明:
当
当
记
我们把这些图像都画一下。
观察到
所以
当取了
保留
显然这还是一个下凸函数。(其实这个证明很不严谨,感性理解吧)
基于证明,我们尝试维护
第一个问题是用什么维护拐点。用一个可重集维护,每一个元素都记录一个拐点;当一个元素重复出现,比如出现了
最左侧的起始点,就是
第二个问题是
容易想到,只要把所有
第三个问题是
观察上面证明的图像变化。
- 把斜率
的全部改成斜率 ,也就是把斜率 的拐点全部 pop 了。 - 把斜率
的那一段,向右平移 格。在做完 后,最靠右的两个拐点一定是斜率 的那一段。把它们取出来,都 再放回去即可。 - "斜率
的那一段的左端点" 到 "它左侧的拐点" 的斜率改成 。其实在做 的时候就已经顺便做了。
到这里已经可以做了。但是我们可以再多观察一个性质,更加优美地写代码。
因为每个
所以
维护拐点的集合,因为只会从右边删,用左偏树即可。
注意到我们其实并不需要同时维护
当我们拥有了
但是这里还有一个方法,可以简化我们求函数值的过程。首先
注意到拐点总个数是
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 6e5 + 5;
struct Node {
ll val;
int l, r, d;
Node() {
val = l = r = 0;
d = -1;
}
Node(ll v) {
val = v;
l = r = d = 0;
}
};
int sz = 0;
Node a[N];
int new_Node(ll v) { //新建一个权值为v的结点
a[++sz] = Node(v);
return sz;
}
int mrg(int L, int R) { //合并以L,R为根的左偏树,返回最终根结点
if (L == 0 || R == 0)
return L + R;
if (a[L].val < a[R].val)
swap(L, R);
a[L].r = mrg(a[L].r, R);
if (a[a[L].l].d < a[a[L].r].d)
swap(a[L].l, a[L].r);
a[L].d = a[a[L].r].d + 1;
return L;
}
int pop(int x) { //弹出x,顺便返回新堆的根结点
return mrg(a[x].l, a[x].r);
}
int rt[N]; //rt[i]记录结点i的左偏树的根
int n, m;
int p[N], c[N]; //父结点,到父结点的边权
int sons[N] = {}; //儿子个数
int main() {
cin >> n >> m;
ll f10 = 0;
for (int i = 2; i <= n + m; i++) {
cin >> p[i] >> c[i];
f10 += c[i];
sons[p[i]]++;
}
for (int i = n + m; i >= 2; i--) {
for (int j = 1; j < sons[i]; j++) //第一步:弹出所有斜率>0的
rt[i] = pop(rt[i]);
//第二步:把斜率0的那一段向右平移len(c[i])
ll R = a[rt[i]].val;
rt[i] = pop(rt[i]);
ll L = a[rt[i]].val;
rt[i] = pop(rt[i]);
rt[i] = mrg(rt[i], mrg(new_Node(L + c[i]), new_Node(R + c[i])));
//第三步:右端改成斜率1的,已经完成
//当前结点的F合并到父结点的f
rt[p[i]] = mrg(rt[p[i]], rt[i]);
}
//把f1的斜率>0的也pop了,这样堆顶就是最低点
for (int j = 1; j < sons[1]; j++)
rt[1] = pop(rt[1]);
rt[1] = pop(rt[1]); //把slope=0的右端点pop了
while (rt[1]) {
f10 -= a[rt[1]].val;
rt[1] = pop(rt[1]);
}
cout << f10 << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!