MY*****

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;

  

posted on 2011-10-20 07:49  reflec94  阅读(435)  评论(1编辑  收藏  举报

导航