GDSOI2008鱼肉炸弹

//树形DP
uses math;
type tre=record
           left,right,fa:longint;
           end;
var t:array[0..100000]of tre;
    tree:array[1..100000,0..2]of longint;
    h,c,stack:array[1..100000]of longint;
    d:array[0..100000,0..5]of int64;
    root,n,k:longint;

procedure writel;
var i,j:longint;
    ans:int64;
begin
ans:=high(int64);
for i:=0 to k do
  ans:=min(ans,d[root,i]);
writeln(ans);
end;

procedure DP(x:longint);
var i,j,j1,j2,l:longint;
begin
if x=0 then exit;
DP(t[x].left);
DP(t[x].right);
for i:=0 to k do
  for j:=0 to k-i do
    begin
      d[x,i+j]:=min(max(d[t[x].left,i],d[t[x].right,j])+c[x],d[x,i+j]);
      if i+j+1<=k then
        d[x,i+j+1]:=min(max(d[t[x].left,i],d[t[x].right,j]),d[x,i+j+1]);
    end;
end;

procedure maketree;
var i,j,top,tot:longint;
begin
top:=0;
for i:=1 to n do
  begin
    {t[i].st:=h[i];
    if top<>0 then
      begin
        tot:=top;
        top:=i;
        while (h[i]>t[tot].st)and(t[tot].fa<>0) do
          tot:=t[tot].fa;
        if h[i]>t[tot].st then
          t[tot].fa:=i;
        if (t[tot].fa<>0)and(tot<>top) then
          begin
            t[i].fa:=t[tot].fa;
            t[tot].fa:=i;
          end;
        if (t[tot].fa<>0)and(tot=top) then
          t[i].fa:=tot;
      end
    else
      top:=1;}
    j:=Top;
    while (j>0)and(h[Stack[j]]Top then
      t[Stack[j+1]].fa:=i;
    if j<>0 then
      t[i].fa:=Stack[j];
    Top:=j+1;
    Stack[Top]:=i;
  end;
for i:=1 to n do
  if t[i].fa=0 then
    root:=i
  else
    begin
      inc(tree[t[i].fa,0]);
      tree[t[i].fa,tree[t[i].fa,0]]:=i;
    end;
for i:=1 to n do
  begin
    t[i].left:=tree[i,1];
    t[i].right:=tree[i,2];
  end;
end;

procedure init;
var i,j:longint;
begin
readln(n,k);
for i:=1 to n do
  readln(h[i],c[i]);
end;

begin
init;
maketree;
fillchar(d,sizeof(d),127);
d[0,0]:=0;
DP(root);
writel;
end.

你可能感兴趣的:(DP)