bzoj3156防御准备 斜率优化dp

3156: 防御准备

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 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

Katharon+#1

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
",f[n]);
34     return 0;
35 }
原文地址:https://www.cnblogs.com/wsy01/p/8125938.html