3156: 防御准备
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 795 Solved: 378
[ Submit][ Status][ Discuss]
Description
Input
第一行为一个整数N表示战线的总长度。
第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。
Output
共一个整数,表示最小的战线花费值。
Sample Input
10
2 3 1 5 4 5 6 3 1 2
Sample Output
18
HINT
1<=N<=10^6,1<=Ai<=10^9
解题思路:
最普通的斜率优化DP,注意细节。。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
long long n;
long long tail=0,head=0;
long long q[1100001];
long long f[1100001];
long long a[1100001];
double work(long long x,long long y)
{
double zhi=f[y]+double(y*y)/2-f[x]-double(x*x)/2;
zhi=zhi/double(y-x);
return zhi;
}
int main()
{
scanf("%lld",&n);
for (int i=n;i>=1;--i)
{
scanf("%lld",&a[i]);
}
f[1]=a[1];
++tail; q[tail]=1;
for (int i=2;i<=n;++i)
{
double zan=double(i)-0.5;
while (head+1<tail && work(q[head+1],q[head+2])<zan)
{
++head;
} long long x1=i-q[head+1]-1,y1=i-q[head+1];
f[i]=(x1*y1)/2+f[q[head+1]]+a[i];
while (head+1<tail && work(q[tail-1],q[tail])>work(q[tail],i))
{
--tail;
}
++tail;
q[tail]=i;
}
for (int i=1;i<=n-1;++i)
{
long long x1=n-i+1; long long y1=n-i;
f[n]=min(f[n],f[i]+(x1*y1)/2);
}
cout<<f[n];
}