【题解】[CEOI2004]锯木厂选址
\(\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\)):
\]
\]
\]
这时,令:\(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]锯木厂选址的更多相关文章
- luoguP4360 [CEOI2004]锯木厂选址
题目链接 luoguP4360 [CEOI2004]锯木厂选址 题解 dis:后缀和 sum:前缀和 补集转化,减去少走的,得到转移方程 dp[i] = min(tot - sumj * disj - ...
- P4360 [CEOI2004]锯木厂选址
P4360 [CEOI2004]锯木厂选址 这™连dp都不是 \(f_i\)表示第二个锯木厂设在\(i\)的最小代价 枚举1号锯木厂 \(f_i=min_{0<=j<i}(\sum_{i= ...
- 动态规划(斜率优化):[CEOI2004]锯木厂选址
锯木场选址(CEOI2004) 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能按照一个方向运输:朝山下运.山脚下有 ...
- [BZOJ2684][CEOI2004]锯木厂选址
BZOJ权限题! Description 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能按照一个方向运输:朝山下运 ...
- LG4360 [CEOI2004]锯木厂选址
题意 原题来自:CEOI 2004 从山顶上到山底下沿着一条直线种植了 n 棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能朝山下运.山脚下有一个锯木厂 ...
- cogs 362. [CEOI2004]锯木厂选址
★★★ 输入文件:two.in 输出文件:two.out 简单对比 时间限制:0.1 s 内存限制:32 MB 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来. ...
- 2018.08.28 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化dp)
传送门 一道斜率优化dp入门题. 是这样的没错... 我们用dis[i]表示i到第三个锯木厂的距离,sum[i]表示前i棵树的总重量,w[i]为第i棵树的重量,于是发现如果令第一个锯木厂地址为i,第二 ...
- 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化)
传送门 我可能根本就没有学过斜率优化…… 我们设$dis[i]$表示第$i$棵树到山脚的距离,$sum[i]$表示$w$的前缀和,$tot$表示所有树运到山脚所需要的花费,$dp[i]$表示将第二个锯 ...
- 【文文殿下】[CEOI2004]锯木厂选址 题解
题解 我们枚举建厂的位置,发现有个\(n^2\)的DP.随手搞个斜率优化到\(O(n)\). #include<bits/stdc++.h> using namespace std; ty ...
随机推荐
- 文件属性及find命令总结
第1章 文件属性 1.1 文件的属性 1.1.1 查看文件的详细属性 PS:ls查看的文件或目录默认的是按照名字的第一个字母进行正序排序 ls 参数选项: -t ...
- jq cdn地址
百度CDN支持版本2.0.3, 2.0.2, 2.0.1, 2.0.0,1.11.1, 1.10.2, 1.10.1, 1.10.0, 1.9.1, 1.9.0, 1.8.3, 1.8.2, 1.8. ...
- Cython编译独立的可执行文件
cython --embed -o hello.c hello.pygcc hello.c -o hello -I /Library/Frameworks/Python.framework/Versi ...
- C# aspx 禁止文本款输入缓的几种方法
1 在ASP.NET中可以在页面中加入以下内容: <%@ OutputCache Location="None" VaryByParam="None" ...
- golang 内置print/println、fmt、log的区别
fmt.Println与fmt.Print区别 换行区别不用多说,另外一个区别在于fmt.Print只有在参数间都不是字符串时才会产生间隔 fmt与log的重要区别 fmt没有做同步处理 fmt标准输 ...
- InnoDB 引擎中的索引类型
首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书本的目录一样,能否快速的查找到你需要的信息,取决于你设计的目录是否合理. MySQL ...
- oracle数据处理之exp/imp
oracle 导出/导入数据方法一 exp/imp工具:1 将数据库oracle01完全导出,DBA:sys,密码:123456:用户名Scott 密码123456 导出到D:\emp.dmp中 ex ...
- [LeetCode]72. 编辑距离(DP)
题目 给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 . 你可以对一个单词进行如下三种操作: 插入一个字符 删除一个字符 替换一个字符 示例 1 ...
- 【二叉树-最长路径系列(任意路径)】直径、最长同值路径、 最大路径和(DFS、树形DP)
总述 这类题目都是求一个最长路径,这个路径可以不经过根节点. 使用dfs(即递归地遍历树)的方法.维护一个全局最长路径max作为最终结果,而递归方法dfs返回的是含根节点的最长路径.(若不使用全局变量 ...
- 如何创建本地git分支到远程
创建本地分支到远程: 1.$git init 之后创建的本地仓库默认master分支 如果现在就要$ git branch 查看当前分支,是不显示任何分支的,只有在add,commit文件之后才显示, ...