Luogu4655 [CEOI2017]Building Bridges

有 \(n\) 根柱子依次排列,每根柱子都有一个高度。第 \(i\) 根柱子的高度为 \(h_i\) 。

现在想要建造若干座桥,如果一座桥架在第 \(i\) 根柱子和第 \(j\) 根柱子之间,那么需要 \((h_i-h_j)^2\) 的代价。

在造桥前,所有用不到的柱子都会被拆除,因为他们会干扰造桥进程。第 \(i\) 根柱子被拆除的代价为 \(w_i\) 。

现在政府想要知道,通过桥梁把第 \(1\) 根柱子和第 \(n\) 根柱子连接的最小代价。注意桥梁不能在端点以外的任何地方相交。

\(n\leq10^5,\ 0\leq h_i,\ |w_i|\leq10^6\)

斜率优化,cdq分治


考虑计算所有拆除柱子的贡献,再在转移过程中消去

于是得到一个状态转移方程

\[f_i=\begin{cases}\displaystyle\sum_{i=2}^n w_i&(i=1)\\\displaystyle\min\{f_j+(h_i-h_j)^2-w_i\}&(i>1)\end{cases}
\]

答案即为 \(f_n\)

于是就有了一个优秀的 \(O(n^2)\) 的过不去算法了

然而这玩意儿是可以斜率优化的

通过一番套路地化式子,可以得到

\[f_j+h_j^2=2h_ih_j+f_i-h_i^2+w_i
\]

令 \(h_j\) 为横坐标, \(f_j+h_j^2\) 为纵坐标, \(2h_i\) 为斜率

然后……可以发现 \(h_j\) 不是递增的……

这就意味着……需要支持插入,询问前驱后继,以及一些复杂的分类讨论……

我会平衡树维护动态凸包!

然而有更好的离线解决办法:cdq分治

强制让斜率递增然后计算贡献

回想cdq分治的过程,左右递归,计算左侧对右侧的贡献

如果左侧斜率递增,并且左侧编号小于右侧,那么可以通过单调队列维护左侧的凸包来更新右侧答案

并且这样一定能够遍历出每个节点的所有决策点

注意 \(long\ long\) ,以及求斜率时 \(x_1=x_2\) 的情况

时间复杂度 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
using namespace std; typedef double db;
typedef long long ll;
const int maxn = 1e5 + 10;
ll f[maxn];
int n, w[maxn]; struct node {
int x, tid; ll y;
} a[maxn], dat[maxn]; ll sqr(ll x) { return x * x; }
db slope(int x, int y) {
if (a[x].x == a[y].x) {
return a[x].y < a[y].y ? 1e18 : -1e18;
}
return db(a[x].y - a[y].y) / db(a[x].x - a[y].x);
} void cdq(int l, int r) {
if (l == r) {
a[l].y = f[a[l].tid] + sqr(a[l].x);
return;
}
int mid = (l + r) >> 1;
for (int i = l, p1 = l, p2 = mid + 1; i <= r; i++) {
if (a[i].tid <= mid) {
dat[p1++] = a[i];
} else {
dat[p2++] = a[i];
}
}
for (int i = l; i <= r; i++) {
a[i] = dat[i];
}
cdq(l, mid);
int L = 1, R = 0;
static int q[maxn];
for (int i = l; i <= mid; i++) {
while (L < R && slope(q[R - 1], q[R]) > slope(q[R], i)) R--;
q[++R] = i;
}
for (int i = mid + 1; i <= r; i++) {
while (L < R && slope(q[L], q[L + 1]) < 2 * a[i].x) L++;
int x = a[i].tid, y = a[q[L]].tid;
f[x] = min(f[x], f[y] + sqr(a[i].x - a[q[L]].x) - w[x]);
}
cdq(mid + 1, r);
for (int i = l, p1 = l, p2 = mid + 1; i <= r; i++) {
if (p2 > r || (p1 <= mid && a[p1].x < a[p2].x)) {
dat[i] = a[p1++];
} else {
dat[i] = a[p2++];
}
}
for (int i = l; i <= r; i++) {
a[i] = dat[i];
}
} int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i].x);
a[i].tid = i, f[i] = 1ll << 60;
}
f[1] = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", w + i);
if (i > 1) f[1] += w[i];
}
sort(a + 1, a + n + 1, [](node a, node b) {
return a.x < b.x;
});
cdq(1, n);
printf("%lld", f[n]);
return 0;
}

2019.4.30 upd: 我发现这玩意儿好像是WC2013被提出来的……

Luogu4655 [CEOI2017]Building Bridges的更多相关文章

  1. 题解-[CEOI2017]Building Bridges

    [CEOI2017]Building Bridges 有 \(n\) 个桥墩,高 \(h_i\) 重 \(w_i\).连接 \(i\) 和 \(j\) 消耗代价 \((h_i-h_j)^2\),用不到 ...

  2. ceoi2017 Building Bridges(build)

    Building Bridges(build) 题目描述 A wide river has nn pillars of possibly different heights standing out ...

  3. 洛谷.4655.[CEOI2017]Building Bridges(DP 斜率优化 CDQ分治)

    LOJ 洛谷 \(f_i=s_{i-1}+h_i^2+\min\{f_j-s_j+h_j^2-2h_i2h_j\}\),显然可以斜率优化. \(f_i-s_{i-1}-h_i^2+2h_ih_j=f_ ...

  4. [CEOI2017]Building Bridges

    题目 斜率优化思博题,不想写了 之后就一直\(95\)了,于是靠肮脏的打表 就是更新了一下凸壳上二分斜率的写法,非常清爽好写 就当是挂个板子了 #include<algorithm> #i ...

  5. 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 ...

  6. HDU 4584 Building bridges (水题)

    Building bridges Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) ...

  7. 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就过了 ...

  8. LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges

    题目传送门:LOJ #2483. 题意简述: 有 \(n\) 个数,每个数有高度 \(h_i\) 和价格 \(w_i\) 两个属性. 你可以花费 \(w_i\) 的代价移除第 \(i\) 个数(不能移 ...

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

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

随机推荐

  1. Linux下ps -ef和ps aux的区别

    Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux.这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格, ...

  2. Hadoop2.0伪分布式平台环境搭建

    一.搭建环境的前提条件 环境:ubuntu-16.04 hadoop-2.6.0  jdk1.8.0_161.这里的环境不一定需要和我一样,基本版本差不多都ok的,所需安装包和压缩包自行下载即可. 因 ...

  3. C# 字符串转byte数组

    public static byte[] HexstringToByte(string InString) { string[] ByteStrings; ByteStrings = InString ...

  4. 微信小程序开发之多图片上传+服务端接收

    前言: 业务需求,这次需要做一个小程序同时选中三张图片一起上传到服务端,后端使用的.NET WEBAPI接收数据保存. 使用技术: 在这章中将会使用到微信小程序wx.uploadFile(Object ...

  5. python基础-函数(9)

    一.函数的介绍 如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数 函数的语法格式: def 函数名(): 函数的功能代码 ...

  6. 消费阿里云日志服务SLS

    此文档只关心消费接入,不关心日志接入,只关心消费如何接入,可直接跳转到[sdk消费接入] SLS简介 日志服务: 日志服务(Log Service,简称 LOG)是针对日志类数据的一站式服务,在阿里巴 ...

  7. 【Keras篇】---Keras初始,两种模型构造方法,利用keras实现手写数字体识别

    一.前述 Keras 适合快速体验 ,keras的设计是把大量内部运算都隐藏了,用户始终可以用theano或tensorflow的语句来写扩展功能并和keras结合使用. 二.安装 Pip insta ...

  8. 尴尬的事情又发生Newtonsoft.Json vs Protobuf.net

    写程序做下性能测试都是例行的事情了,一般在普通电脑上测试一下如果比较理想那基本不出什么意外!但世事难料,代码写得不好经常担心CPU不够用,其实写得好但不能完全发挥出CPU资源的优势更是一件悲剧的事情! ...

  9. Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! WebFlux 系列教程大纲 一.背景 大家都知道,Sprin ...

  10. 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?

    简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...