传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=3156
题目大意
每个点可以建个守卫塔(给定价格),或者向右移动到最近的守卫塔(价格为距离)询问最小价格
题解
dp[i]=min{dp[j]+(i−j)∗(i−j−1)2+x[i]}
dp[i]=min{dp[j]+j2−2ij+j2}+i2−i+x[i]
假设j<k且k更优
dp[j]+j2−2ij+j2>dp[k]+k2−2ik+k2
dp[j]−dp[k]>k2−2ik+k2−j2−2ij+j2
dp[j]−dp[k]−k2+k−j2−j2>i(j−k)
j−k<0
dp[j]−dp[k]−k2+k−j2−j2j−k<i
const
maxn=1000005;
var
dp,x:array[0..maxn]of int64;
t:array[0..maxn]of longint;
i,j,k,n,tt,l,r:longint;
function f(a,b:longint):real;
var c,d,e:real;
begin
c:=a; d:=b;
e:=(dp[a]-dp[b]+(c*c+c-d*d-d)/2)/(c-d);
exit(e);
end;
begin
readln(n);
for i:=1 to n do
read(x[i]);
l:=1; r:=1; t[1]:=0;
for i:=1 to n do
begin
while (l<r)and(f(t[l],t[l+1])<=i) do inc(l);
tt:=t[l]; dp[i]:=dp[tt]+x[i]+((i-tt)*(i-tt-1))div 2;
while (l<r)and(f(t[r-1],t[r])>f(t[r],i)) do dec(r);
inc(r); t[r]:=i;
end;
writeln(dp[n]);
{fillchar(dp,sizeof(dp),0);
for i:=1 to n do
begin
dp[i]:=maxlongint;
for j:=0 to i-1 do
if dp[j]+x[i]+((i-j)*(i-j-1))div 2<dp[i]
then begin tt:=j; dp[i]:=dp[j]+x[i]+((i-j)*(i-j-1))div 2; end;
writeln(i,' ',dp[i],' ',tt);
end;
writeln(dp[n]);}
end.