洛谷P3628 [APIO2010]特别行动队(动态规划,斜率优化,单调队列)

洛谷题目传送门

安利蒟蒻斜率优化总结

由于人是每次都是连续一段一段地选,所以考虑直接对x记前缀和,设现在的xi=原来的j=1ixi

fi为安排前i个人的最大值(f0=0)

fi=maxj=0i1{fj+a(xixj)2+b(xixj)+c}
=maxj=0i1{fj2axixj+axj2bxj}+axi2+bxi+c

决策jk优当且仅当

fj2axixj+axj2bxjfk2axixk+axk2bxk

fj+axj2bxj(fk+axk2bxk)xjxk2axi

于是每个决策可以看成是一个点(xi,yi)(yi=fi+axi2bxi)

不用考虑变号。因为a<0xi递增,斜率2axi递减,所以我们用单调队列维护一个下凸包就行了。依旧是维护队首为当前最优解。

当然注意这里的转移是从0i1,所以和土地征用有点点不一样,要先求出fi再加入决策点i

纯天然代码

#include<cstdio>
#define RG register
#define R RG int
#define G c=getchar()
#define Calc(j,k) (y[j]-y[k])/(x[j]-x[k])//求斜率
const int N=1e6+9;
int q[N];
double f[N],k[N],x[N],y[N];//变量名同上
inline int in(){
	RG char G;RG bool f=0;
	while(c<'-')G;
	if(c=='-')f=1,G;
	R x=c&15;G;
	while(c>'-')x=x*10+(c&15),G;
	return f?-x:x;
}
int main(){
	R n=in(),i,h,t;
	RG double a=in(),b=in(),c=in(),now;
	for(i=h=t=1;i<=n;++i){
		x[i]=x[i-1]+in();//前缀和
		now=2*a*x[i];//当前斜率
		while(h<t&&k[h]>=now)++h;
		f[i]=-now*x[q[h]]+y[q[h]]+(a*x[i]+b)*x[i]+c;//先求fi,根据定义式求
		y[i]=f[i]+(a*x[i]-b)*x[i];//yi跟着求
		while(h<t&&k[t-1]<=Calc(q[t],i))--t;//维护凸包
		k[t]=Calc(q[t],i);q[++t]=i;
	}
	printf("%.0lf\n",f[n]);
	return 0;
}
posted @   Flash_Hu  阅读(284)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
剑桥
17:14发布
剑桥
17:14发布
5°
西风
7级
空气质量
相对湿度
34%
今天
多云
-3°/5°
周六
-1°/3°
周日
-2°/7°