poj 3017 cut the sequence

分析:不好理解,大体上知道了优化的方向,但是需要单调队列和平衡树(或堆)来维护。

比较难以理解。

f[i]=min{f[k]+max{a[k+1],.....,a[i]}}.

n2的枚举没有问题,优化势在必行。

我们另A[I,J]表示i到j的最大值,那么如果A[i+1,j]=A[i+2,j],那么f[i]+A[i+1,j]<f[i+1]+A[i+2,j],

所以很显然f[i]=min{f[k]+A[k+1,i]}有用的K值都是满足某段区间的最大值。

如果用单调队列维护a[i]使队列中的元素a值单调递减,那么显然可以用于更新的就是a[q[i]]+f[q[i-1]],但是与其他题目不同的是队首元素并不是最优的,所以可以用堆或者平衡树来迅速找到最大值。

核心代码:

procedure ins(c,d:longint);

begin

  sum:=sum+c;

  while sum>m do

    begin

      inc(last);

      sum:=sum-a[last];

    end;

  while (v[tail]<=c) and(tail>head) do

    begin

      delete(z[tail]);

      dec(tail);

    end;

  inc(tail);

  v[tail]:=c;

  p[tail]:=d;

end;



procedure solve;

var

  i: longint;

begin

  for i:= 1 to n do

    begin

      ins(a[i],i);

      while p[head+1]<last do

        begin

          inc(head);

          delete(z[head]);

        end;

      p[head]:=last;

      delete(z[head+1]);

      insert(f[p[head]]+v[head+1],head+1,z[head+1]);

      insert(f[p[tail-1]]+v[tail],tail,z[tail]);

      f[i]:=h1[1];

    end;

  writeln(f[n]);

end;

  

你可能感兴趣的:(sequence)