版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/83385000
Time Limit: 10 Sec Memory Limit: 512 MB
Description
Input
第一行为一个整数N表示战线的总长度。
第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。
Output
共一个整数,表示最小的战线花费值。
HINT
题目分析
表示前
个检查点都能通过,且第
个检查点放防御塔所需最小费用
首先有
的方程
即
~
都放木偶
展开再移项
即
为
,
为
,
为斜率进行斜率优化
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
typedef double dd;
#define sqr(x) ((x)*(x))
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxn=2000010;
int n;
lt ai[maxn],dp[maxn];
int q[maxn],ll,rr;
lt qans(lt i,lt j){ return dp[j]+(sqr(j)+j+sqr(i)-i)/2-i*j+ai[i];}
dd calc(lt j1,lt j2)
{
lt ty=(dp[j2]+(sqr(j2)+j2)/2)-(dp[j1]+(sqr(j1)+j1)/2);
lt tx=j2-j1;
return (dd)ty/(dd)tx;
}
int main()
{
n=read();
for(int i=1;i<=n;++i) ai[i]=read();
ll=rr=1;
for(int i=1;i<=n;++i)
{
while( ll<rr && calc(q[ll],q[ll+1])<=i ) ++ll;
dp[i]=qans(i,q[ll]);
while( ll<rr && calc(q[rr-1],q[rr])>=calc(q[rr],i)) --rr;
q[++rr]=i;
}
printf("%lld",dp[n]);
return 0;
}