P2120 [ZJOI2007] 仓库建设

题目大意

\(n\) 个工厂,每个工厂有 \(p_i\) 的货物,货物运输一个单位距离的费用是 \(1\),工厂可以建造仓库,费用为 \(c_i\)。工厂与工厂 \(1\) 的距离为 \(x_i\)。要求将货物运送到下一个最近的仓库,求最小费用。

\(1\leq n\leq 10^6\)

思路

先考虑最基本的动规:
\(f_i\) 表示在这里建仓库时 \([1,i]\) 的转移与建造的最小费用。则有方程:

\[f_i=\min(f_j+\sum_{k=j+1}^i(x_i-x_k)p_k)+c_i) \]

化简:

\[f_i=\min(f_j+\sum_{k=j+1}^ix_ip_k-\sum_{k=j+1}^ix_kp_k+c_i) \]

\[f_i=\min(f_j+x_i\sum_{k=j+1}^ip_k-\sum_{k=j+1}^ix_kp_k+c_i) \]

\(s_x=\sum_{i=1}^x p_i\)\(v_x=\sum_{i=1}^x x_ip_i\),则原式化为:

\[f_i=\min(f_j+x_i(s_i-s_j)-(v_i-v_j)+c_i) \]

\[f_i=\min(f_j+x_is_i-x_is_j-v_i+v_j+c_i) \]

整理一下就是设函数 \(F_k(x)=-s_kx+f_k+v_k\)\(C_k=s_kx_k-v_k+c_k\) 则原式就转化成了斜率优化可以做的样子:

\[f_i=\min(F_j(x_i)+C_i) \]

对于要求的 \(f_i\),维护 \(F_k\) 其中 \(k\in[0,i)\)。之后找到一个最优的 \(F_k\) 使得 \(F_k(x_i)\) 能取到最低点。换句话说我们维护的是一个凸包。像:
image
这里的紫色部分显然就是答案。之后考虑维护。

观察到 \(s\) 严格单调递增,即 \(F_k\) 的斜率 \(-s_k\) 严格单调下降,换句话说只要当前的这个函数不够优秀那我们以后都不再会选择了。可以考虑将函数维护成单调队列。发现凸包会被交点分成一段一段,则我们只要删除的时候发现交点大于 \(x_i\) 就可以舍去。则之后的 \(f_i\) 可以设成 \(f_i=F_{\text{front}}(x_i)+C_i\),其中 \(\text{front}\) 指单调队列队首。然后考虑插入 \(F_i\)。可以直接用当前的最后一个交点与次大函数与 \(F_i\) 的交点进行比较,如果小的话就可以继续出队列,直到更新不好为止,之后插入 \(F_i\)

求函数交点很好求。对于 \(y_0=kx+b\)\(y_1=px+q\) 来说它们的交点就是

\[kx+b=px+q \]

\[kx-px=q-b \]

\[x=\frac{q-b}{k-p} \]

特别的,在插入函数时如果它们的斜率一样就可以直接取截距小的那个,因为它们平行(或重合),当然取截距小的。

代码

#include<bits/stdc++.h>
#define v(u,x) (u.a*1.0*x+u.b)
using namespace std;
typedef long long ll;
typedef long double ld;
const ll MAXN=1e6+5;
struct Func{ld a,b;Func(ld _a,ld _b){a=_a;b=_b;}
};
ld jd(Func p,Func q){if(p.a==q.a){if(p.b>=q.b){return 1e18;} return -1e18;}return (q.b-p.b)*1.0/(p.a-q.a);
}
ll sxp[MAXN],sp[MAXN];
ll n;
ll x[MAXN],p[MAXN],c[MAXN]; 
ll f[MAXN];
deque<Func>dq;
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=n;++i){cin>>x[i]>>p[i]>>c[i];sp[i]=sp[i-1]+p[i];sxp[i]=sxp[i-1]+x[i]*p[i];}dq.push_back(Func(0,0));for(int i=1;i<=n;++i){while(dq.size()>1){Func F=dq.front();dq.pop_front();if(jd(dq.front(),F)>x[i]){dq.push_front(F);break;}}f[i]=v(dq.front(),x[i])+sp[i]*x[i]-sxp[i]+c[i];Func nw=Func(-sp[i],f[i]+sxp[i]);while(dq.size()>1){Func F=dq.back();dq.pop_back();if(jd(dq.back(),F)<jd(dq.back(),nw)){dq.push_back(F);break;}}dq.push_back(nw);}ll ans=1e18;for(int i=n;i>=1;--i){ans=min(ans,f[i]);if(p[i]){cout<<ans<<endl;return 0;}}return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/742975.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何对Linux系统进行基准测试5工具UnixBench

UnixBenchUnixBench是一款跨平台基准测试工具,用于评估各种类Unix系统(包括Linux、BSD和macOS)的系统性能。它提供了一套全面的测试套件,可评估系统性能的不同方面,包括:系统调用: 此测试衡量进行系统调用的开销,系统调用是应用程序与操作系统内核交互的主要方式。 文件…

解决vscode项目中无法识别宏定义的问题

在c_cpp_properties.json中的"defines":[]中定义的宏无法被识别。 从而导致代码中的宏开关无法生效,造成代码的阅读不便利。 排查路线是: 关闭所有插件,删除当前工程目录下的.vscode文件夹。 经过一系列排查发现是C/C++插件与clangd插件有冲突, 解决方法很简单,…

vs使用AnkhSVN冲突

he problem seems to be the (as the error hints) the propertybag within the solution file问题似乎是解决方案文件中的 propertybag(如错误提示的那样) So a work around of this issue:因此,此问题的解决方法:You have a "solution.sln" created with VS 20…

0175-GDB 调试 multiboot 启动

环境Time 2022-11-12 WSL-Ubuntu 22.04 QEMU 6.2.0 NASM 2.15.05前言 说明 参考:https://os.phil-opp.com/multiboot-kernel/ 目标 使用编写好的内核可执行文件,直接从 QEMU 启动,启动时暂停 CPU,使用 GDB 调试。 汇编代码 section .multiboot_header header_start:dd 0x1B…

0172-执行内核文件

环境Time 2022-11-11 WSL-Ubuntu 22.04 QEMU 6.2.0 NASM 2.15.05前言 说明 参考:https://os.phil-opp.com/multiboot-kernel/ 目标 将编写好的内核可执行文件,制作成 ISO 镜像,然后从 QEMU 启动。 建立文件目录 isofiles └── boot├── grub│ └── grub.cfg└── …

TDA4VM-SK配置与应用杂谈

TDA4VM-SK配置与应用杂谈硬件信息:SK-TDA4VM 用户指南处理器SDK Linux边缘AI文档配置文档:SK-TDA4VM处理器SDK Linux文档-getting_started,详细说明了如何配置,下面是简要步骤:物料准备: SK板,microUSB串口线,USB camera,HDMI/DP显示器,≥16GB的内存卡,网线和局域网…

(技术贴)英雄无敌1——永久记住所学魔法——手把手教你怎么修改

喜欢英雄无敌1的朋友都知道,在1中英雄学习魔法只是记忆了该魔法的使用次数,一旦次数使用完,该魔法就会从魔法书中消失!而要想再次使用该魔法,就得去具有该魔法的魔法公会再次学习一次,自然这很不符合魔法学习的实际情况。我这里将其修改为,学过的魔法永远记住!但是学过…

连接mysql时提示is not allowed to connect不允许连接

1. 进入mysql服务器,mysql -u root -p 登录myql服务,SELECT user, host FROM mysql.user;看到root只允许localhost本机连接 2. 执行use mysql; update user set host = % where user = root; 再次查看user表,root允许所有ip连接 3.刷新缓存FLUSH PRIVILEGES; 以上仅供参考…

LCA 补充

LCA 之前学废了,回来补。 倍增版 首先是最常见的倍增版子,思路好理解,按倍增记录 \(father\),然后同时往上跳。 注意最后跳到的是那个 \(x \ne y\) 的,也就是 \(lca\) 的儿子,所以最后要返回父亲。 #include<bits/stdc++.h> using namespace std; const int N = 5e…

读人工智能全传11人工智能会出什么错

读人工智能全传11人工智能会出什么错1. 人工智能会出什么错 1.1. 一些报道是公正合理的,不过坦白地说,大部分报道都愚蠢得无可救药 1.2. 一些报道颇有知识性和引导性,而大部分则是杞人忧天式的恐吓 1.3. 滑稽的报道迎合了大众对人工智能的“终结者式恐惧” 1.3.1. 我们创造出…

dotnet 理解 X11 的 24 位或 32 位色深窗口

本文记录在 X11 里面的窗口与颜色的位色深关系本文属于学习 CPF 框架博客,感谢小红帽的 CPF 框架。更多关于 CPF 框架,请参阅 https://gitee.com/csharpui/CPF 本文这里的 24 色或 32 色表示的是用多少个 bit 表示一个像素的颜色。比如常见的 24 色就是 RGB 三个颜色分量,一…

【C++】const与constexpr

const 用于声明该变量是一个常量。 可以用来声明成员函数,表示该函数不会改变成员变量。 const修饰指针的场景稍微复杂点,可以通过循环的方式记忆:constexpr constexpr 它是在 C++ 11 被引进的,它的字面意思是 constant expression,常量表达式。它可以作用在变量和函数上。…