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. 探索JS引擎工作原理

    JavaScript 从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习 JS 引擎工作机制之前,我们需要引入几个相关的概念:执行环境栈.全局对象.执行环境.变量对象.活动对象.作用域和作用 ...

  2. Linux知识要点大全(第四章)

    第四章 文件管理 *主要内容 文件和目录的操作: ①创建 ②删除 ③拷贝 ④重命名(剪切) ⑤查看 一:目录的操作 回顾与目录相关的命令 ls  查看目录中的内容 .pwd 打印当前目录   .cd  ...

  3. 网络协议 20 - RPC 协议(上)- 基于XML的SOAP协议

    [前五篇]系列文章传送门: 网络协议 15 - P2P 协议:小种子大学问 网络协议 16 - DNS 协议:网络世界的地址簿 网络协议 17 - HTTPDNS:私人定制的 DNS 服务 网络协议 ...

  4. TabTopUnderLineLayout【自定义顶部选项卡(带下划线)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 自定义顶部选项卡布局LinearLayout类,实现带下划线样式的效果. 备注:如果配合Fragment的话,MainActivit ...

  5. 强化学习(三)用动态规划(DP)求解

    在强化学习(二)马尔科夫决策过程(MDP)中,我们讨论了用马尔科夫假设来简化强化学习模型的复杂度,这一篇我们在马尔科夫假设和贝尔曼方程的基础上讨论使用动态规划(Dynamic Programming, ...

  6. Java 集合详解

    一.集合的由来 通常,我们的程序需要根据程序运行时才知道创建多少个对象.但若非程序运行,程序开发阶段,我们根本不知道到底需要多少个数量的对象,甚至不知道它的准确类型.为了满足这些常规的编程需要,我们要 ...

  7. 从PRISM开始学WPF(番外)共享上下文 RegionContext-更新至Prism7.1

    RegionContext共享上下文 There are a lot of scenarios where you might want to share contextual information ...

  8. angr学习

    0.资料 几个主要的网站 angr的github:https://github.com/angr angr的document:https://docs.angr.io/ angr的api:https: ...

  9. Cayley图数据库的简介及使用

    图数据库   在如今数据库群雄逐鹿的时代中,非关系型数据库(NoSQL)已经占据了半壁江山,而图数据库(Graph Database)更是攻城略地,成为其中的佼佼者.   所谓图数据库,它应用图理论( ...

  10. [MySQL] mysql的逻辑分层

    mysql逻辑分层:1.client ==>连接层 ==>服务层==>引擎层==>存储层 server2.连接层: 提供与客户端连接的服务3.服务层: 1.提供各种用户使用的接 ...