My understanding:
Note: (I) represents a formula that contains only I unknowns
Status transfer is shown in the following expression:
Dp [I] = dp [j] + (j, I );
Dp [I] = dp [k] + (k, I );
Assume that j is better than k for I.
So dp [j] + (j, I)
If the preceding formula can be converted to: dp [j] + (j)-(dp [k] + (k)/(j)-(k) <(I)
Then we can use slope Optimization for optimization:
Set g [j, k] <(I) to indicate that when I is in the I state, selecting j state is better than selecting k State.
For g [I] [j]
If g [I] [j] <(I), the I state is better than the j state, and the j state is discarded.
If g [I] [j]> = (I), then g [j] [k]> = (I), the k State is better than the j state, then, discard the j state.
That is:
If g [I] [j] exists
#include
#include
#include#include
using namespace std;#define maxn 550000struct list{ int x; int val;} node[maxn],p;int a[maxn];int sum[maxn];int dp[maxn];int gety(int x,int y){ return dp[x]+sum[x]*sum[x]-dp[y]-sum[y]*sum[y];}int tan(int x,int y,int z){ int ay=gety(z,y); int by=gety(y,x); int ax=2*(sum[z]-sum[y]); int bx=2*(sum[y]-sum[x]); if(ay*bx<=by*ax)return 1; return 0;}int pan(int a,int b,int c){ int ay=gety(b,a); int ax=2*(sum[b]-sum[a]); if(ay<=sum[c]*ax)return 1; return 0;}int main(){ int n,m,i; while(~scanf(%d%d,&n,&m)) { sum[0]=0; for(i=1; i<=n; i++) { scanf(%d,&a[i]); sum[i]=sum[i-1]+a[i]; } int head,tail; head=1; tail=0; p.x=0; node[++tail]=p; memset(dp,0,sizeof(dp)); for(i=1; i<=n; i++) { p.x=i; while(tail>head&&pan(node[head].x,node[head+1].x,i))head++; int x=node[head].x; dp[i]=dp[x]+m+(sum[i]-sum[x])*(sum[i]-sum[x]); while(tail>head&&tan(node[tail-1].x,node[tail].x,i))tail--; node[++tail]=p; } cout<