ceoi2017 Building Bridges(build)_fswiwi-程序员宅基地

技术标签: cdq  dp  分治  

Building Bridges(build)

题目描述

 

A wide river has nn pillars of possibly different heights standing out of the water. They are arranged in a straight line from one bank to the other. We would like to build a bridge that uses the pillars as support. To achieve this we will select a subset of pillars and connect their tops into sections of a bridge. The subset has to include the first and the last pillar.

The cost of building a bridge section between pillars ii and jj is (hi−hj)2(hi−hj)2 as we want to avoid uneven sections, where hihi is the height of the pillar ii. Additionally, we will also have to remove all the pillars that are not part of the bridge, because they obstruct the river traffic. The cost of removing the i−thi−th pillar is equal to wiwi. This cost can even be negative—some interested parties are willing to pay you to get rid of certain pillars. All the heights hihi and costs wiwi are integers.

What is the minimum possible cost of building the bridge that connects the first and last pillar?

 

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

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

在造桥前,所有用不到的柱子都会被拆除,因为他们会干扰造桥进程。第 i 根柱子被拆除的代价为 wi,注意 wi 不一定非负,因为可能政府希望拆除某些柱子。
现在政府想要知道,通过桥梁把第 1 根柱子和第 n 根柱子连接的最小代价。注意桥梁不能在端点以外的任何地方相交。

 

输入

 

The first line contains the number of pillars, nn.

The second line contains pillar heights hihi in the order, separated by a space.

The third line contains wiwi in the same order, the costs of removing pillars.

 

第一行一个正整数 n。

第二行 n 个空格隔开的整数,依次表示h1,h2,⋯,hnh1,h2,⋯,hn。

第三行 n 个空格隔开的整数,依次表示w1,w2,⋯,wnw1,w2,⋯,wn。

 

 

 

 

 

 

输出

 

Output the minimum cost for building the bridge. Note that it can be negative.

 

输出一行一个整数表示最小代价,注意最小代价不一定是正数。

 

 

 

 

样例输入

6
3 8 7 1 6 6
0 -1 9 1 2 0

样例输出

17

提示

 

Constraints

• 2 <= n <= 10^5

• 0 <= hi <= 10^6

• 0 <= |wi| <= 10^6

Subtask 1 (30 points)

• n <= 1, 000

Subtask 2 (30 points)

• optimal solution includes at most 2 additional pillars (besides the first and last) • |wi| <= 20

Subtask 3 (40 points)

• no additional constraints

 

 

来源

ceoi2017 day2


solution

把w前缀和起来

我们可以得到一个n^ 2 DP

f[i]=f[j]+(h[i]-h[j])*(h[i]-h[j])+w[i-1]-w[j]

把它写成斜率优化的形式

f[i]+2*h[i]*h[j]=f[j]+h[j]*h[j]-w[j]+h[i]*h[i]+w[i-1]

斜率不单调,x不单调。

不会splay,那就cdq分治。

把h排序,然后就是单调的了

构出凸包,斜率优化即可

吐槽:cdq细节真是多

注意算斜率时

有时是+inf (a.x==b.x&&a.y<b.y)

有时是-inf (a.x==b.x&&a.y>b.y)

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
#define inf 1e18
using namespace std;
int n,num[22][maxn],top;
long long f[maxn];
struct node{
    long long id,h,w;
}s[maxn],ss[maxn];
struct po{
    long long x,y,id;
}h[maxn],zh[maxn];
void merge(int k,int l,int r){
    if(l==r){num[k][l]=l;return;}
    int mid=l+r>>1;
    merge(k+1,l,mid);merge(k+1,mid+1,r);
    int li=l,ri=mid+1;
    for(int i=l;i<=r;i++){
        if(li>mid){
            num[k][i]=num[k+1][ri++];continue;
        }
        if(ri>r){
            num[k][i]=num[k+1][li++];continue;
        }
        int v1=s[num[k+1][li]].h,v2=s[num[k+1][ri]].h;
        if(v1<=v2)num[k][i]=num[k+1][li++];
        else num[k][i]=num[k+1][ri++];
    }
}
po xl(po a,po b){
    po t;t.x=a.x-b.x,t.y=a.y-b.y;
    return t;
}
long long cj(po a,po b){
    return a.x*b.y-a.y*b.x;
}
void tb(int l,int r){
    top=0;
    for(int i=l;i<=r;i++){
         
        po now;now.x=s[i].h,now.y=f[s[i].id]+s[i].h*s[i].h-s[i].w;now.id=s[i].id;
        while(top>1&&cj(xl(zh[top],zh[top-1]),xl(now,zh[top]))<=0)top--;
        zh[++top]=now;
    }
}
double getk(po a,po b){
    if(a.x==b.x){
        if(a.y>b.y)return -inf;
        return inf;
    }
    double xx=a.x-b.x,yy=a.y-b.y;
    return yy/xx;
}
void cdq(int k,int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    cdq(k+1,l,mid);
    for(int i=l;i<=mid;i++)s[i]=ss[num[k+1][i]];
     
    tb(l,mid);  
    for(int i=mid+1;i<=r;i++)s[i]=ss[num[k+1][i]];
    int fs=1;
    for(int i=mid+1;i<=r;i++){
        while(fs<top&&2*(double)s[i].h>getk(zh[fs],zh[fs+1]))fs++;
        int j=zh[fs].id,ii=s[i].id;
        f[ii]=min(f[ii],
        f[j]+(ss[ii].h-ss[j].h)*(ss[ii].h-ss[j].h)+ss[ii-1].w-ss[j].w
        );
    }
    for(int i=mid+1;i<=r;i++)s[i]=ss[i];
    cdq(k+1,mid+1,r); 
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%lld",&s[i].h);
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i].w);
        s[i].w+=s[i-1].w;
        s[i].id=i;
        ss[i]=s[i];
    }
    merge(1,1,n);
    for(int i=2;i<=n;i++)f[i]=inf;
    cdq(1,1,n);
    cout<<f[n]<<endl;
    return 0;
}

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liankewei123456/article/details/82287573

智能推荐

Git版本控制使用方法入门教程-程序员宅基地

文章浏览阅读299次。1. 概述对于软件版本管理工具,酷讯决定摒弃CVS而转向Git了。为什么要选择Git? 你真正学会使用Git时, 你就会觉得这个问题的回答是非常自然的。然而当真正需要用文字来回答时,却觉得文字好像不是那么够用。 咳,该则么回答呢?其实,关键的问题不在于如何回答这个问题。 问题的关键是公司已经决定使用它了。那么,我们的程序员们! 请开动你们的浏览器,请拿出你的搜索引擎工具,去_版本控制使用方法

67.二进制求和(简单)-程序员宅基地

文章浏览阅读25次。给你两个二进制字符串a和b,以二进制字符串的形式返回它们的和。

Python 文本处理和语义分析2 使用m3e对文本向量化_m3e-base 数据分析-程序员宅基地

文章浏览阅读1.3k次,点赞26次,收藏15次。向量化将会是下一阶段演进的目标。在过去的实践中,向量或者矩阵其实是最贴近工具端的。以sklearn为例,虽然原始数据可能还是自然语言,但是在最终执行 fit或者predict之前,数据一般都转为了矩阵形态(numpy)。也就是说,在pandas(原始数据)和最终结果(predict result)之间,是(短暂且必然)存在过矩阵的。后来,应该是有过类似以图搜图类的应用,向量化且持久化在数据库中开始兴起。_m3e-base 数据分析

cmd常用操作_source d:/jtsys.sql-程序员宅基地

文章浏览阅读186次。cmd常用操作,易忘…1,查看JDK版本:java -version2,执行sql文件:source 文件路径如:source d:/CGBWORK/jtsys.sql3,备份数据库在cmd窗口中(未登录的状态), 通过mysqldump命令备份数据库:格式: mysqldump -u用户名 -p 备份的库的名字 > 备份文件位置举例: 备份db40库中的所有数据(dept表及..._source d:/jtsys.sql

堆的结构实现与应用-程序员宅基地

文章浏览阅读1k次,点赞25次,收藏32次。我们只要记住关键的两点:1.堆必须是完全二叉树。2.堆要么是大堆,要么是小堆。

python二级题库及答案解析,python二级题库百度网盘-程序员宅基地

文章浏览阅读342次,点赞11次,收藏7次。答案:A 解析:int()函数可以将字符串转换为整数,float()函数可以将字符串转换为浮点数,str()函数可以将任意类型的变量转换为字符串,bool()函数可以将任意类型的变量转换为布尔值。答案:C 解析:input()和print()是Python中常用的输入输出函数,len()用于计算序列中元素的数量。

随便推点

jquery-隐藏和显示_jquery隐藏ul-程序员宅基地

文章浏览阅读1.4k次。jquery hide() / show()先上个效果图通过jquery的hide()show()方法来隐藏/显示html元素语法:$(selector).hide(speed,callback);$(selector).show(speed,callback);(可选的) speed 参数规定隐藏/显示的速度,可取以下值:"slow"、"fast" 或毫秒(可_jquery隐藏ul

JNI实战-Android深度学习模型部署_将深度学习模型封装成jni-程序员宅基地

文章浏览阅读511次。传统方式 java->javac -> .class->javah -jni->.h C/C++实现.h中声明的方法 添加并编写.mk文件 通过CMake工具 CMakeLists.txt 学习资源https://www.jianshu.com/p/b4431ac22ec2_将深度学习模型封装成jni

获取接口重定向后的url,两种方式:-程序员宅基地

文章浏览阅读895次。获取接口重定向后的url的方式

基于java Springboot+Vue+shiro前后端分离疫情防疫管理系统设计和实现2.0 免费源码+论文答辩资料获取_前后端分离java项目答辩论文-程序员宅基地

文章浏览阅读445次。基于java Springboot+Vue+shiro前后端分离疫情防疫管理系统设计和实现2.0目录研究背景主要特性功能:视频效果演示 :主要功能截图:系统首页:疫情数据分布图模拟:用户管理:角色控制:菜单权限:每日健康打卡:历史出行数据:外出报备申请:外出请假审核:疫情通知公告:疫情资料管理:注销修改密码:主要代码实现:主要数据表设计:表clock表file表go_out表info表sys_captcha (系统验证码)表sys_config (系统配置信息表)表sys_log (系统日志)表sys_m_前后端分离java项目答辩论文

graylog--splunk的开源替代-程序员宅基地

文章浏览阅读1.1k次。2019独角兽企业重金招聘Python工程师标准>>> ..._splunk 开源替代

从零开始的目标检测和关键点检测(一):用labelme标注数据集_数据标注labelme-程序员宅基地

文章浏览阅读2.3k次。从零开始的目标检测和关键点检测(一):用labelme标注数据集_数据标注labelme