首先我们发现将一段数变为同一个数比间隔着搞肯定优,
因为数列是升序的,
然后不难得到方程式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  
View Code

 

posted on 2014-09-05 22:24  acphile  阅读(252)  评论(0编辑  收藏  举报