Noi 2009 day1 第三题 二叉查找树

题目:

 二叉查找树

来源:

 Noi 2009 day1 第三题

题目大意:

 神马权值,数据值,访问频率啰嗦一大堆,性质就类似treap,按照数据值排,再保  证权值。访问代价=访问频率*深度,可以花K代价来修改结点权值,从而导致树的结  构变化,求访问代价和与共修改代价的和最小

数据范围:

 N<=70,1<=K<=30000000

样例:

 4 10

 1 2 3 4

 1 2 3 4

 1 2 3 4

29

做题思路:

 动态规划

 f(i,j,k)=min    

   f(i,x-1,k)+f(x+1,j,k)+sum(i,j) ; 权值(x)<=k,或者x是[i,j]之                                                                                                      间权值比k大的结点中最小的一个

                           f(i,x-1,k)+f(x+1,j,k)+sum(i,j);x任意取

                           f(i,j,x)+k; x是[i,j]之间权值比k大的结点中最小的一个

 然后,把这个树抽象了吧,既然数据值不能变,就按它排序,[l,r]表示l到r节点的树。

知识点:

 动态规划,离散化

type
 tre=record
 d,c,p,num:longint;{<数据值,权值,访问频率,离散值>}
 end;
var
 tree:array[0..100]of tre;
 b:array[0..400010]of longint;
 f:array[0..100,0..100,0..100]of longint;
 sum:array[0..100]of longint;
 n,k,m,max,i:longint;
procedure qsort(l,r:longint);
var
 i,j,k:longint;
 t:tre;
begin
 i:=l;j:=r;
 k:=tree[(l+r)shr 1].d;
 repeat
 while tree[i].d<k do inc(i);
 while tree[j].d>k do dec(j);
 if i<=j then
  begin
    t:=tree[i];tree[i]:=tree[j];tree[j]:=t;
    inc(i);dec(j);
  end;
 until i>j;
 if i<r then qsort(i,r);
 if j>l then qsort(l,j);
end;
functionmin(a,b:longint):longint;
begin
 if a>b then exit(b);
 exit(a);
end;
functiondfs(l,r,x:longint):longint;
var
 i:longint;
begin
 if f[l,r,x]<f[0,0,0] then exit(f[l,r,x]); {<记忆化>}
 if l>r then
 begin
  f[l,r,x]:=0;
  exit(0);
 end;
 for i:=l to r do
  begin  f[l,r,x]:=min(f[l,r,x],dfs(l,i-1,x)+dfs(i+1,r,x)+sum[r]-sum[l-1]+k);{<第二种情况>}
  if tree[i].num>x then
    begin
f[l,r,x]:=min(f[l,r,x],dfs(l,i-1,tree[i].num)+dfs(i+1,r,tree[i].num)+sum[r]-sum[l-1]);{<第一种情况>}
    end;
 end;
 exit(f[l,r,x]); {<f[l,r,x]表示由l到r所有结点构成的子树,根节点权值<=x或者l,r之间权值比x大的最小的一个>}
end;
begin
assign(input,'treapmod.in');reset(input);
 assign(output,'treapmod.out');rewrite(output);
 fillchar(b,sizeof(b),0);
 fillchar(sum,sizeof(sum),0);
 fillchar(f,sizeof(f),63); {<63→无穷大>}
 readln(n,k);
 for i:=1 to n do read(tree[i].d);
 max:=-maxlongint; {<找最大,离散化用>}
 for i:=1 to n do
 begin
  read(tree[i].c);
  b[tree[i].c]:=1;
  if max<tree[i].c then max:=tree[i].c;
 end;
 for i:=1 to n do read(tree[i].p);
 qsort(1,n); {<以下一小节是离散化,离散数据值>}
 m:=0;
 for i:=0 to max do
 if b[i]>0 then
  begin
    inc(m);
    b[i]:=m;
  end;
 for i:=1 to n do
 begin
  sum[i]:=sum[i-1]+tree[i].p; {<求访问频率和>}
  tree[i].num:=b[tree[i].c]; {<返回离散化的值>}
 end;
 m:=maxlongint;
 for i:=0 to 1 do
 if m>dfs(1,n,i) then m:=f[1,n,i]; {<根节点变不变,去最小的一个>}
 writeln(m);
 close(input);close(output);
end.
题目来源: http://www.rqnoj.cn/Problem_528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值