3156: 防御准备
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2279 Solved: 959
[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
Source
f[i]=f[j]+(i-j)*i-(sum[i]-sum[j])+a[i]
递推方程式和1096有点类似
sum[i]表示i到1的距离
设k<j && j 优于 k
f[j]+(i-j)*i-(sum[i]-sum[j])+a[i]<=f[k]+(i-k)*i-(sum[i]-sum[k])+a[i]
化简得f[j]-i*j+sum[j]<=f[k]-i*k+sum[k]
证明决策单调性
需要证明 对于 t>i j的决策优于k
即f[j]-t*j+sum[j]<=f[k]-t*k+sum[k]
设t=i+v 代入上式得
f[j]-i*j+sum[j]-v*j<=f[k]-i*k+sum[k]-v*k
-v*j<=-v*k 上式成立 决策单调性得证
证毕
斜率方程式
假设k<j&&j决策优与k
满足f[j]-i*j+sum[j]<=f[k]-i*k+sum[k]
=> f[j]+sum[j]-f[k]-sum[k]<=i*(j-k)
=> (f[j]+sum[j]-f[k]-sum[k])/(j-k)<=i
优化dp即可
1 #include<bits/stdc++.h> 2 #define N 1000005 3 #define ll long long 4 using namespace std; 5 ll sum[N],f[N]; 6 int n,q[N],a[N]; 7 inline char gc(){ 8 static char s[1000000],*p1,*p2; 9 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 10 if(p1==p2)return EOF;return *p1++; 11 } 12 inline int read(){ 13 int x=0;char ch=gc(); 14 while(ch<‘0‘||ch>‘9‘)ch=gc(); 15 while(ch<=‘9‘&&ch>=‘0‘)x=x*10+ch-‘0‘,ch=gc(); 16 return x; 17 } 18 ll U(int k,int j){return f[j]+sum[j]-f[k]-sum[k];} 19 int D(int k,int j){return j-k;} 20 int main(){ 21 n=read(); 22 for(register int i=1;i<=n;++i){ 23 a[i]=read(); 24 sum[i]=sum[i-1]+i; 25 } 26 int h=1,t=1,j; 27 for(register int i=1;i<=n;++i){ 28 while(h<t&&D(q[h],q[h+1])*i>=U(q[h],q[h+1]))++h; 29 j=q[h];f[i]=f[j]+1ll*(i-j)*i-sum[i]+sum[j]+a[i]; 30 while(h<t&&U(q[t],q[t-1])*D(i,q[t])>=U(i,q[t])*D(q[t],q[t-1]))--t; 31 q[++t]=i; 32 } 33 printf("%lld\n",f[n]); 34 return 0; 35 }