Luogu4655 [CEOI2017]Building Bridges
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_n\)
于是就有了一个优秀的 \(O(n^2)\) 的过不去算法了
然而这玩意儿是可以斜率优化的
通过一番套路地化式子,可以得到
\]
令 \(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的更多相关文章
- 题解-[CEOI2017]Building Bridges
[CEOI2017]Building Bridges 有 \(n\) 个桥墩,高 \(h_i\) 重 \(w_i\).连接 \(i\) 和 \(j\) 消耗代价 \((h_i-h_j)^2\),用不到 ...
- ceoi2017 Building Bridges(build)
Building Bridges(build) 题目描述 A wide river has nn pillars of possibly different heights standing out ...
- 洛谷.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_ ...
- [CEOI2017]Building Bridges
题目 斜率优化思博题,不想写了 之后就一直\(95\)了,于是靠肮脏的打表 就是更新了一下凸壳上二分斜率的写法,非常清爽好写 就当是挂个板子了 #include<algorithm> #i ...
- 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 ...
- HDU 4584 Building bridges (水题)
Building bridges Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) ...
- 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就过了 ...
- LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges
题目传送门:LOJ #2483. 题意简述: 有 \(n\) 个数,每个数有高度 \(h_i\) 和价格 \(w_i\) 两个属性. 你可以花费 \(w_i\) 的代价移除第 \(i\) 个数(不能移 ...
- @loj - 2483@「CEOI2017」Building Bridges
目录 @desription@ @solution@ @accepted code@ @details@ @another solution@ @another code@ @desription@ ...
随机推荐
- Kafka的partions和replication-factor参数的理解
Topic在Kafka中是主题的意思,生产者将消息发送到主题,消费者再订阅相关的主题,并从主题上拉取消息. 在创建Topic的时候,有两个参数是需要填写的,那就是partions和replicatio ...
- F#正则表达式
此词法分析器允许您使用F#计算表达式以非常声明的方式定义基于正则表达式的规则. F# 打开 Lexer 让 定义= lexerDefinitions { 做!addNextlineDefinition ...
- RIpng配置(GNS3)(第九组)
一.拓扑图 二.路由器配置 路由器R1的配置(配置RIP静态路由协议,路由器对应接口配置相对应的ipv6地址,并给每个接口配置RIP 1 enable) 路由器R2的配置(配置RIP静态路由协议,路由 ...
- PhotoPickerNewDemo【PhotoPicker0.9.12的个性化修改以及使用(内部glide版本号是4.1.1)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo使用的是PhotoPicker 0.9.12版本,里面集成的glide版本号是4.1.1.这里就不进行特殊的个性化处理了( ...
- 【Python3爬虫】百度一下,坑死你?
一.写在前面 这个标题是借用的路人甲大佬的一篇文章的标题(百度一下,坑死你),而且这次的爬虫也是看了这篇文章后才写出来的,感兴趣的可以先看下这篇文章. 前段时间有篇文章<搜索引擎百度已死> ...
- Session的使用与Session共享问题
Session的使用与Session共享问题 Session方法 getId():获取sessionId,这个id不一定是数字,比方说它用字符串来表示唯一标识,所以它返回值是String; boole ...
- c#多线程总结(纯干货)
线程基础 创建线程 static void Main(string[] args) { Thread t = new Thread(PrintNumbers); t.Start();//线程开始执行 ...
- 4.1ASP.NET Core请求过程「深入浅出ASP.NET Core系列」
希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. HTTP请求过程 这里展示整体的HTTP请求的过程,这里化繁为简,保留了主干流程: 从浏览器输入域名开始,这里忽略 ...
- Springboot 系列(十一)使用 Mybatis(自动生成插件) 访问数据库
1. Springboot mybatis 介绍 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数获取 ...
- 命令提示符-bash-4.1$错误解决
有时候在使用用户登陆Linux系统时会发现,命令行提示符成了:-bash-4.1$,不显示用户名,路径信息. 原因:用户家目录里面与环境变量有关的文件被删除所导致的 也就是这俩文件:.bash_pro ...