Link

\(\text{Solution:}\)

注意到题目中的编号是倒着的,于是我们的距离要预处理的是后缀和。

考虑如何\(n^2\)搞:

设\(dp[i]\)表示选择\(i\)为第二个中转点的最小代价。

枚举在\(i\)前面的\(j\),代价就是\(dp[i]=\min_{j<i}All-dis[j]*sum[j]-dis[i]*(sum[i]-sum[j])\)

\(All\)是所有树木运输到\(1\)号点的代价。可以理解为,有一部分运输到\(j\)就不用运了,于是把这部分减掉。\(sum\)是重量的前缀和。

枚举前一个点,显然是\(n^2\)的(虽然这样可以过)

考虑优化,先推柿子(令\(S=All\)):

\[dp[i]=S-dis[j]*sum[j]-dis[i]*(sum[i]-sum[j])
\]
\[dis[j]*sum[j]=S-dp[i]-dis[i]*sum[i]+dis[i]*sum[j]
\]
\[dis[j]*sum[j]=dis[i]*sum[j]+(S-dp[i]-dis[i]*sum[i])
\]

这时,令:\(y=dis[j]*sum[j],k=dis[i],x=sum[j],b=(S-dp[i]-dis[i]*sum[i])\),一个一次函数式出来了。

显然的斜率优化,但是这里有一个坑,害得我看博客又理解了半天……

其实,如果按照最小化截距来写,会发现这就是一个下凸壳,即使\(dis[i]\)是递减而非递增。但是看了题解后发现,维护的是一个上凸壳。

为什么?

考虑我们究竟要最小化还是最大化。

如果最小化\(b=(S-dp[i]-dis[i]*sum[i])\),则因为\(dp[i]\)前面的符号是负的,所以我们就反其道而行之地把它给最大化了。于是\(\text{Wrong Answer.}\)

所以,实际上我们要最大化截距\(b\),从而最小化\(dp[i]\).

于是我们的任务就变成维护一个上凸包了。观察到\(dis[i]\)递减,于是我们只保留小于\(dis[i]\)的线段。因为后面的最优线段一定是斜率递减的。

我们通过上述分析,可以通过单调队列优化到\(O(n).\)

这题的主要价值在于,注意\(b\)的符号,不是题目中要求\(min\)就一定是下凸包,也不是题目中求最大值就一定是下凸包。看截距的时候要特别留意\(dp[i]\)——我们最关心的值的符号,以此来确定维护上凸壳还是下凸壳。

#include<bits/stdc++.h>
using namespace std;
int n,w[200010],d[200010];
int s[200010],sum[200010];
int dp[200010],ans=0;
int head,tail,q[200010];
int dis[200010],S,A=2147483647;
int Y(int x){return dis[x]*sum[x];}
int X(int x){return sum[x];}
double slope(int x,int y){return (Y(y)-Y(x))/(X(y)-X(x));}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d%d",&w[i],&dis[i]);
for(int i=n;i>=1;--i)dis[i]+=dis[i+1];
for(int i=1;i<=n;++i)ans+=dis[i]*w[i];
for(int i=1;i<=n;++i)sum[i]=sum[i-1]+w[i];
//Dis[i]>(dis[k]*sum[k]-dis[j]*sum[j])/(sum[k]-sum[j])
//Dp[i]=S-dis[j]*sum[j]-dis[i]*(sum[i]-sum[j])
//Dis[j]*sum[j]=dis[i]*sum[j]+(S-dp[i]-dis[i]*sum[i])
//最小化后面一坨 斜率是dis[i]
//head=tail=1;q[head]=1;
//cout<<ans<<endl;
for(int i=1;i<=n;++i){
while(head<tail&&slope(q[head],q[head+1])>=dis[i])head++;
dp[i]=ans-dis[q[head]]*sum[q[head]]-dis[i]*(sum[i]-sum[q[head]]);
//cout<<dp[i]<<" ";
A=min(A,dp[i]);
while(head<tail&&slope(q[tail-1],q[tail])<=slope(q[tail-1],i))--tail;
q[++tail]=i;
}
printf("%d\n",A);
return 0;
}

【题解】[CEOI2004]锯木厂选址的更多相关文章

  1. luoguP4360 [CEOI2004]锯木厂选址

    题目链接 luoguP4360 [CEOI2004]锯木厂选址 题解 dis:后缀和 sum:前缀和 补集转化,减去少走的,得到转移方程 dp[i] = min(tot - sumj * disj - ...

  2. P4360 [CEOI2004]锯木厂选址

    P4360 [CEOI2004]锯木厂选址 这™连dp都不是 \(f_i\)表示第二个锯木厂设在\(i\)的最小代价 枚举1号锯木厂 \(f_i=min_{0<=j<i}(\sum_{i= ...

  3. 动态规划(斜率优化):[CEOI2004]锯木厂选址

    锯木场选址(CEOI2004) 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能按照一个方向运输:朝山下运.山脚下有 ...

  4. [BZOJ2684][CEOI2004]锯木厂选址

    BZOJ权限题! Description 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能按照一个方向运输:朝山下运 ...

  5. LG4360 [CEOI2004]锯木厂选址

    题意 原题来自:CEOI 2004 从山顶上到山底下沿着一条直线种植了 n 棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能朝山下运.山脚下有一个锯木厂 ...

  6. cogs 362. [CEOI2004]锯木厂选址

    ★★★   输入文件:two.in   输出文件:two.out   简单对比 时间限制:0.1 s   内存限制:32 MB 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来. ...

  7. 2018.08.28 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化dp)

    传送门 一道斜率优化dp入门题. 是这样的没错... 我们用dis[i]表示i到第三个锯木厂的距离,sum[i]表示前i棵树的总重量,w[i]为第i棵树的重量,于是发现如果令第一个锯木厂地址为i,第二 ...

  8. 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化)

    传送门 我可能根本就没有学过斜率优化…… 我们设$dis[i]$表示第$i$棵树到山脚的距离,$sum[i]$表示$w$的前缀和,$tot$表示所有树运到山脚所需要的花费,$dp[i]$表示将第二个锯 ...

  9. 【文文殿下】[CEOI2004]锯木厂选址 题解

    题解 我们枚举建厂的位置,发现有个\(n^2\)的DP.随手搞个斜率优化到\(O(n)\). #include<bits/stdc++.h> using namespace std; ty ...

随机推荐

  1. java 区块

    方法区:存放staic变量,方法签名,类信息,字段等 堆:存放对象数据,string常量 栈:存放对象的引用,操作数,没逃逸但是逃逸分析且被编译器产生逃逸优化的对象数据

  2. MySQL数据库中几种数据类型的长度

    在MySQL里新建表自然会涉及设置字段长度,但有时会发现长度限制在一些字段类型中不起作用?字段长度是按字节算还是字符算? 如图中:int看起来只要还在本身类型取值范围内就行,字段长度没有起到作用:而c ...

  3. 手写mybatis框架

    前言 很久没有更新mybatis的源码解析了,因为最近在将自己所理解的mybatis思想转为实践. 在学习mybatis的源码过程中,根据mybatis的思想自己构建了一个ORM框架 .整个代码都是自 ...

  4. java安全编码指南之:声明和初始化

    目录 简介 初始化顺序 循环初始化 不要使用java标准库中的类名作为自己的类名 不要在增强的for语句中修改变量值 简介 在java对象和字段的初始化过程中会遇到哪些安全性问题呢?一起来看看吧. 初 ...

  5. nginx的gzip压缩

    随着nginx的发展,越来越多的网站使用nginx,因此nginx的优化变得越来越重要,今天我们来看看nginx的gzip压缩到底是怎么压缩的呢? gzip(GNU-ZIP)是一种压缩技术.经过gzi ...

  6. Q200510-02-02: 重复的DNA序列 SQL解法

    重复的DNA序列所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”.在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数来 ...

  7. Thymeleaf中model设一个值 页面显示此值 JS取此值

    model设值: m.addAttribute("pageNo", pageNo); 页面显示值: 当前为第:<span th:text="${pageNo}&qu ...

  8. 重学Ajax

    什么是Ajax Asynchronous JavaScript and xml 异步的JavaScript和XML 只是一种js的应用,在无需重新加载整个网页的情况下实现部分网页的数据更新的技术.减少 ...

  9. 关于Nginx mmap(MAP_ANON|MAP_SHARED, 314572800)报错

    mmap 报错解决 今天修改了一下测试环境的Nginx的nginx.conf,然后做检测的时候报了一个错误 /usr/local/bin/nginx -c /usr/local/etc/openres ...

  10. 超详细!盘点Python中字符串的常用操作

    在Python中字符串的表达方式有四种 一对单引号 一对双引号 一对三个单引号 一对三个双引号 a = 'abc' b= "abc" c = '''abc''' d = " ...