首先我们发现将一段数变为同一个数比间隔着搞肯定优,
因为数列是升序的,
然后不难得到方程式f[i]=min(f[j]+sum[i]-sum[j]-(i-j)*a[j+1]) (i-j>=m)
简单的斜率优化不多说
注意这道题最优解有选择范围,也就是说要延迟入队
1 var a,s,f:array[0..500010] of int64; 2 q:array[0..500010] of longint; 3 j,t,i,n,m,h,r:longint; 4 5 function G(j,k:int64):int64; 6 begin 7 exit(f[j]-f[k]+s[k]-s[j]+a[j+1]*j-a[k+1]*k); 8 end; 9 10 function P(j,k:int64):int64; 11 begin 12 exit(a[j+1]-a[k+1]); 13 end; 14 15 function value(i,j:int64):int64; 16 begin 17 exit(f[j]+s[i]-s[j]-a[j+1]*(i-j)); 18 end; 19 20 begin 21 readln(t); 22 while t>0 do 23 begin 24 dec(t); 25 readln(n,m); 26 s[0]:=0; 27 for i:=1 to n do 28 begin 29 read(a[i]); 30 s[i]:=s[i-1]+a[i]; 31 end; 32 f[0]:=0; 33 q[0]:=0; 34 h:=0; 35 r:=0; 36 for i:=1 to n do 37 begin 38 while (h<r) and (G(q[h+1],q[h])<=int64(i)*P(q[h+1],q[h])) do inc(h); 39 f[i]:=value(i,q[h]); 40 if (i>=2*m-1) and (i<>n) then 41 begin 42 while (h<r) and (G(i-m+1,q[r])*P(q[r],q[r-1])<=G(q[r],q[r-1])*P(i-m+1,q[r])) do dec(r); 43 inc(r); 44 q[r]:=i-m+1; 45 end; 46 end; 47 writeln(f[n]); 48 end; 49 end. 50 51