【洛谷P3628】特别行动队
题目
题目链接:https://www.luogu.com.cn/problem/P3628
你有一支由 名预备役士兵组成的部队,士兵从 到 编号,你要将他们拆分成若干特别行动队调入战场。出于默契的考虑,同一支特别行动队中队员的编号应该连续,即为形如 的序列。所有的队员都应该属于且仅属于一支特别行动队。
编号为 的士兵的初始战斗力为 ,一支特别行动队的初始战斗力 为队内士兵初始战斗力之和,即 。
通过长期的观察,你总结出对于一支初始战斗力为 的特别行动队,其修正战斗力 ,其中 是已知的系数()。 作为部队统帅,现在你要为这支部队进行编队,使得所有特别行动队的修正战斗力之和最大。试求出这个最大和。
。
思路
不记得从哪听说这道题不是很模板?但是感觉还是模板啊QWQ。
设 表示前 个人分好组的最大和。设 ,显然
展开,移项后得到
那么可以看做一条斜率为 ,截距为 的直线,决策点为 的平面直角坐标系。
由于 ,那么斜率满足单调递减,同时决策点的横坐标单调递增,所以单调队列维护上凸壳即可。
时间复杂度 。
代码
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1000010;
ll a,b,c,f[N],s[N],Y[N];
int n,l,r,q[N];
ll read()
{
ll d=0,f=1; char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d*f;
}
double slope(int x,int y)
{
return 1.0*(Y[y]-Y[x])/(s[y]-s[x]);
}
int main()
{
n=read(); a=read(); b=read(); c=read();
for (int i=1;i<=n;i++)
s[i]=s[i-1]+read();
l=r=1;
for (int i=1;i<=n;i++)
{
for (int x=q[l],y=q[l+1];;x=q[l],y=q[l+1])
if (l<r && slope(x,y)>=2.0*a*s[i]) l++;
else break;
int j=q[l];
f[i]=f[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c;
Y[i]=f[i]+a*s[i]*s[i]-b*s[i];
for (int x=q[r-1],y=q[r];;x=q[r-1],y=q[r])
if (l<r && slope(x,y)<=slope(y,i)) r--;
else break;
q[++r]=i;
}
printf("%lld",f[n]);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 为DeepSeek添加本地知识库
· .NET程序员AI开发基座:Microsoft.Extensions.AI
· 精选4款基于.NET开源、功能强大的通讯调试工具
· 数据不出内网:基于Ollama+OneAPI构建企业专属DeepSeek智能中台
· 大模型工具KTransformer的安装