poj 3709 K-Anonymous Sequence

终于把最后一道优化DP的题目做了,斜率优化之前掌握的不是非常熟练呀。

朴素方程:f[i]=min{f[k]+s[i]-s[k]-a[k+1]*(i-k)}。

就这么一个朴素方程的化简,搞了很久。

把减号写成加号导致化简完全错误,纠结于直接用double还是用int64的x和y,后来有纠结于≤和≥的问题。这才完全搞定斜率优化。不错的题目。

代码:

var

  q,f,s,a:array[0..500002] of int64;

  head,tail,n,m,i,j,t:longint;

  k,xx,yy,zz:int64;



function y(k,j:longint):int64;

begin

  exit(f[k]-f[j]+s[j]-s[k]-a[j+1]*j+a[k+1]*k);

end;



function x(k,j:longint):int64;

begin

  exit(a[k+1]-a[j+1]);

end;



begin

  readln(t);

  while t>0 do

    begin

      dec(t);

      readln(n,m);

      for i:=1 to n do

        begin

          read(a[i]);

          s[i]:=s[i-1]+a[i];

        end;

      f[0]:=0;

      head:=0;

      tail:=0;

      q[0]:=0;

      for i:=1 to n do

        begin

          while (head<tail)and(y(q[head],q[head+1])>=i*x(q[head],q[head+1]))

          do inc(head);

          k:=q[head];

          f[i]:=f[k]+s[i]-s[k]-a[k+1]*(i-k);

          if i>=2*m-1 then

            begin

              zz:=i-m+1;

              while head<tail do

                begin

                  xx:=q[tail-1];

                  yy:=q[tail];

                  if y(xx,yy)*x(yy,zz)>=(y(yy,zz)*x(xx,yy)) then dec(tail)

                  else break;

                end;

              inc(tail);

              q[tail]:=zz;

            end;

         end;

      writeln(f[n]);

    end;

end.

  

你可能感兴趣的:(sequence)