题目传送门:LOJ #2483

题意简述:

有 \(n\) 个数,每个数有高度 \(h_i\) 和价格 \(w_i\) 两个属性。

你可以花费 \(w_i\) 的代价移除第 \(i\) 个数(不能移除第 \(1\) 个和第 \(n\) 个数)。

这之后,没有被移除的数中,相邻两个数 \(i\) 和 \(j\) 会产生 \((h_j-h_i)^2\) 的代价。

求最小代价。

题解:

斜率优化 DP。

考虑 \(\mathrm{f}[i]\) 表示只考虑前 \(i\) 个数的最小代价,易得转移 \(\displaystyle\mathrm{f}[i]=\min_{j=1}^{i-1}(\mathrm{f}[j]+(h_i-h_j)^2+s_{i-1}-s_j)\)。

其中 \(s_n\) 表示 \(\displaystyle\sum_{i=1}^{n}w_i\)。

简化式子:\(\displaystyle\mathrm{f}[i]=h_i^2+s_{i-1}+\min_{j=1}^{i-1}(\mathrm{f}[j]+h_j^2-s_j-2h_ih_j)\)。显然可以看出斜率优化的形式。

考虑两个合法转移点 \(j\) 和 \(k\),比较 \(j\) 和 \(k\) 转移的优劣:

\[\begin{aligned}\mathrm{f}[j]+h_j^2-s_j-2h_i\times h_j&\Leftrightarrow\mathrm{f}[k]+h_k^2-s_k-2h_i\times h_k\\(\mathrm{f}[k]+h_k^2-s_k)-(\mathrm{f}[j]+h_j^2-s_j)&\Leftrightarrow 2h_i\times(h_k-h_j)\end{aligned}
\]

\(x\) 坐标是 \(h_i\),\(y\) 坐标是 \(\mathrm{f}[i]+h_i^2-s_i\)。假设 \(x_j<x_k\),则决策 \(j\) 比 \(k\) 优当且仅当:

\[\begin{aligned}\mathrm{f}[j]+h_j^2-s_j-2h_i\times h_j&<\mathrm{f}[k]+h_k^2-s_k-2h_i\times h_k\\y_k-y_j&>2h_i\times(x_k-x_j)\\\frac{y_k-y_j}{x_k-x_j}&>2h_i\end{aligned}
\]

即点 \((x_j,y_j)\) 和点 \((x_k,y_k)\) 之间的线段的斜率大于 \(2h_i\)。

因为 \(x_i=h_i\) 不单调,所以需要动态维护下凸壳,这可以通过使用平衡树维护解决,复杂度 \(\mathcal{O}(n\log n)\)。

也可以使用 CDQ 分治的方法解决,分治左半边后考虑按照 \(h_i\) 排序,使用单调队列在线性复杂度内得到下凸壳,以及线性更新答案。

这里的排序可以使用归并排序,不会提高复杂度,但是我为了方便直接使用了快速排序,时间复杂度 \(\mathrm{O}(n\log^2n)\)。

#include <cstdio>
#include <cstring>
#include <algorithm> typedef long long LL;
const int MN = 100005; int N, p[MN], tmp[MN];
LL h[MN], w[MN], f[MN], X[MN], Y[MN]; inline double Slope(int i, int j) {
if (X[i] == X[j]) return 1e50 * (Y[j] - Y[i]);
return (double)(Y[j] - Y[i]) / (X[j] - X[i]);
} int que[MN], l, r;
void Solve(int lb, int rb) {
if (lb == rb) { Y[lb] += f[lb]; return ; }
int mid = (lb + rb) >> 1;
Solve(lb, mid);
for (int i = lb; i <= rb; ++i) p[i] = i;
std::sort(p + lb, p + rb + 1, [](int i, int j) { return h[i] < h[j]; });
l = 1, r = 0;
for (int i = lb; i <= rb; ++i) if (p[i] <= mid) {
while (l < r && Slope(que[r - 1], que[r]) >= Slope(que[r], p[i])) --r;
que[++r] = p[i];
}
for (int i = lb; i <= rb; ++i) if (p[i] > mid) {
while (l < r && Slope(que[l], que[l + 1]) <= 2 * h[p[i]]) ++l;
f[p[i]] = std::min(f[p[i]], f[que[l]] + (h[p[i]] - h[que[l]]) * (h[p[i]] - h[que[l]]) + w[p[i] - 1] - w[que[l]]);
}
Solve(mid + 1, rb);
} int main() {
scanf("%d", &N);
for (int i = 1; i <= N; ++i) scanf("%lld", &h[i]);
for (int i = 1; i <= N; ++i) scanf("%lld", &w[i]), w[i] += w[i - 1];
for (int i = 1; i <= N; ++i) p[i] = i, X[i] = h[i], Y[i] = h[i] * h[i] - w[i];
memset(f, 0x7f, sizeof f);
f[1] = 0, Solve(1, N);
printf("%lld\n", f[N]);
return 0;
}

LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges的更多相关文章

  1. loj#2483. 「CEOI2017」Building Bridges 斜率优化 cdq分治

    loj#2483. 「CEOI2017」Building Bridges 链接 https://loj.ac/problem/2483 思路 \[f[i]=f[j]+(h[i]-h[j])^2+(su ...

  2. LOJ 3045: 洛谷 P5326: 「ZJOI2019」开关

    题目传送门:LOJ #3045. 题意简述 略. 题解 从高斯消元出发好像需要一些集合幂级数的知识,就不从这个角度思考了. 令 \(\displaystyle \dot p = \sum_{i = 1 ...

  3. LOJ 3089: 洛谷 P5319: 「BJOI2019」奥术神杖

    题目传送门:LOJ #3089. 题意简述: 有一个长度为 \(n\) 的母串,其中某些位置已固定,另一些位置可以任意填. 同时给定 \(m\) 个小串,第 \(i\) 个为 \(S_i\),所有位置 ...

  4. LOJ 3093: 洛谷 P5323: 「BJOI2019」光线

    题目传送门:LOJ #3093. 题意简述: 有 \(n\) 面玻璃,第 \(i\) 面的透光率为 \(a\),反射率为 \(b\). 问把这 \(n\) 面玻璃按顺序叠在一起后,\(n\) 层玻璃的 ...

  5. LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树

    题目传送门:LOJ #3043. 题意简述: 你需要模拟线段树的懒标记过程. 初始时有一棵什么标记都没有的 \(n\) 阶线段树. 每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间 ...

  6. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  7. LOJ 2249: 洛谷 P2305: 「NOI2014」购票

    题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...

  8. loj#2483. 「CEOI2017」Building Bridges(dp cdq 凸包)

    题意 题目链接 Sol \[f[i], f[j] + (h[i] - h[j])^2 + (w[i - 1] - w[j]))\] 然后直接套路斜率优化,发现\(k, x\)都不单调 写个cdq就过了 ...

  9. @loj - 2483@「CEOI2017」Building Bridges

    目录 @desription@ @solution@ @accepted code@ @details@ @another solution@ @another code@ @desription@ ...

随机推荐

  1. 【题解】 bzoj3956: Count (ST表+单调栈)

    题面 Solution 看了一点点题解,自己又刚了\(2h30min\),刚了出来qwq,我好菜啊qwq 貌似这道题是BZOJ 4826的弱化,弱化都不会qwq凉凉 Solution 首先你可以考虑, ...

  2. BZOJ 3503 [CQOI2014]和谐矩阵

    题目链接 BZOJ 3503 题解 没想到--直接用暴力的\(O((nm)^3)\)算法,居然能过?! 高斯消元解异或方程组. #include <cstdio> #include < ...

  3. [poj3278]抓住那头牛

    题目描述 Farmer John has been informed of the location of a fugitive cow and wants to catch her immediat ...

  4. helm详解

    helm 可以理解为 Kubernetes 的包管理工具,可以方便地发现.共享和使用为Kubernetes构建的应用. 一.基本概念1.Helm的三个基本概念Chart:Helm应用(package) ...

  5. Linux:进程实例信息(/proc)

    https://blog.csdn.net/test1280/article/details/73632333 Linux:进程实例信息(/proc) 问几个问题: 1.怎么知道一个进程对应哪个可执行 ...

  6. C# 获得本机IP、端口等信息地址以及服务器IP信息

    大概是这样子,代码也没多少,直接上代码了.. 引入命名空间: using System.Net; namespace IPExample { public partial class Form1 : ...

  7. jdbc操作数据库(详细)

    JDBC是由java编程语言编写的类及接口组成,同时它为程序开发人员提供了一组用于实现对数据库访问的JDBC API,并支持SQL语言.利用JDBC可以将JAVA代码连接到oracle.DB2.SQL ...

  8. 洛谷【P2458】[SDOI2006]保安站岗 题解 树上DP

    题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...

  9. 结尾非零数的奇偶性(问题来源于PythonTip)

    给你一个正整数列表 L, 判断列表内所有数字乘积的最后一个非零数字的奇偶性.如果为奇数输出1,偶数则输出0.. 例如:L=[2,8,3,50] 则输出:0 L = [2,8,3,50] c2 = 0 ...

  10. 搞定 Kubernetes 基于flannel 的集群网络

    .Docker网络模式 在讨论Kubernetes网络之前,让我们先来看一下Docker网络.Docker采用插件化的网络模式,默认提供bridge.host.none.overlay.maclan和 ...