HDU 2829 Lawrence (斜率DP)
斜率DP
设dp[i][j]表示前i点,炸掉j条边的最小值。j<i
dp[i][j]=min{dp[k][j-1]+cost[k+1][i]}
又由得出cost[1][i]=cost[1][k]+cost[k+1][i]+sum[k]*(sum[i]-sum[k])
cost[k+1][i]=cost[1][i]-cost[1][k]-sum[k]*(sum[i]-sum[k])
代入DP方程
可以得出 y=dp[k][j-1]-cost[1][k]+sum[k]^2
x=sum[k].
斜率sum[i]
const maxn=2008; var n,m,i,j,h,t:longint; a,sum,cost,q:array[0..maxn*10] of int64; f:array[0..maxn,0..maxn] of int64; function kx(x,y:int64):int64; begin exit(sum[x]-sum[y]); end; function ky(x,y:int64):int64; begin exit((f[x,j-1]-cost[x]+sum[x]*sum[x])-(f[y,j-1]-cost[y]+sum[y]*sum[y])) end; begin readln(n,m); for i:=1 to n do read(a[i]); for i:=1 to n do sum[i]:=sum[i-1]+a[i]; for i:=1 to n do cost[i]:=cost[i-1]+a[i]*sum[i-1]; for i:=1 to n do f[i,0]:=cost[i]; for i:=1 to n do f[i,i-1]:=0; for j:=1 to m do begin h:=0; t:=1; q[1]:=j; for i:=j+1 to n do begin while (h<t) and (kx(q[h+1],q[h])*sum[i]>ky(q[h+1],q[h])) do inc(h); f[i,j]:=-sum[i]*sum[q[h]]+f[q[h],j-1]-cost[q[h]]+sum[q[h]]*sum[q[h]]+cost[i]; while (h<t) and (ky(i,q[t])*kx(q[t],q[t-1])<=ky(q[t],q[t-1])*kx(i,q[t])) do dec(t); inc(t); q[t]:=i; end; end; writeln(f[n,m]); end.