【NOI2009】 二叉查找树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
二叉查找树 【问题描述】 已知一棵特殊的二叉查找树。根据定义,该二叉查找树中每个结点的数据值都比它左子树结点的数据值大,而比它右子树结点的数据值小。 另一方面,这棵查找树中每个结点都有一个权值,每个结点的权值都比它的儿子结点的权值要小。 已知树中所有结点的数据值各不相同;所有结点的权值也各不相同。这时可得出这样一个有趣的结论:如果能够确定树中每个结点的数据值和权值,那么树的形态便可以唯一确定。因为这样的一棵树可以看成是按照权值从小到大顺序插入结点所得到的、按照数据值排序的二叉查找树。 一个结点在树中的深度定义为它到树根的距离加1。因此树的根结点的深度为1。 每个结点除了数据值和权值以外,还有一个访问频度。我们定义一个结点在树中的访问代价为它的访问频度乘以它在树中的深度。整棵树的访问代价定义为所有结点在树中的访问代价之和。 现在给定每个结点的数据值、权值和访问频度,你可以根据需要修改某些结点的权值,但每次修改你会付出K的额外修改代价。你可以把结点的权值改为任何实数,但是修改后所有结点的权值必须仍保持互不相同。现在你要解决的问题是,整棵树的访问代价与额外修改代价的和最小是多少? 【输入文件】 输入文件名为treapmod.in。 输入文件第一行包含两个正整数N和K。N为结点的个数,K为每次修改所需的额外修改代价。 接下来一行包含N个非负整数,是每个结点的数据值。 再接下来一行包含N个非负整数,是每个结点的权值。 再接下来一行包含N个非负整数,是每个结点的访问频度。 所有的数据值、权值、访问频度均不超过400000。每两个数之间都有一个空格分隔,且行尾没有空格。 【输出文件】 输出文件名为treapmod.out。输出文件只有一个数字,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值。 【输入样例】 4 10 1 2 3 4 1 2 3 4 1 2 3 4 【输出样例】 29 【样例说明】 输入的原图是左图,它的访问代价是1×1+2×2+3×3+4×4=30。最佳的修改方案是把输入中的第3个结点的权值改成0,得到右图,访问代价是1×2+2×3+3×1+4×2=19,加上额外修改代价10,一共是29。 原图略。 【数据规模】 40%的数据满足N ≤ 30; 70%的数据满足N ≤ 50; 100%的数据满足N ≤ 70, 1 ≤ K ≤ 30000000。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 program treapmod; 2 uses math; 3 const maxn=100; 4 maxnum=1000000000; 5 type 6 ty=record 7 s,q,f:longint; 8 end; 9 var 10 n,k,i:longint; 11 a:array[0..maxn] of ty; 12 s:array[0..maxn] of longint; 13 f:array[0..maxn,0..maxn,0..maxn] of longint; 14 //================== 15 procedure sort(l,r,k:longint); 16 var 17 i,j,m:longint; 18 t:ty; 19 begin 20 i:=l; j:=r; 21 if k=1 then m:=a[(l+r) >> 1].q else m:=a[(l+r) >> 1].s; 22 repeat 23 if k=1 then 24 begin 25 while a[i].q<m do inc(i); 26 while a[j].q>m do dec(j); 27 end else 28 begin 29 while a[i].s<m do inc(i); 30 while a[j].s>m do dec(j); 31 end; 32 if i<=j then 33 begin 34 t:=a[i]; a[i]:=a[j]; a[j]:=t; 35 inc(i); dec(j); 36 end; 37 until i>j; 38 if i<r then sort(i,r,k); 39 if j>l then sort(l,j,k); 40 end; 41 //================== 42 function find(i,j,w:longint):longint; 43 var 44 x:longint; 45 begin 46 if i>j then exit(0); 47 if f[i,j,w]>-1 then exit(f[i,j,w]); 48 f[i,j,w]:=maxnum; 49 for x:=i to j do 50 begin 51 if a[x].q>=w then 52 f[i,j,w]:=min(f[i,j,w],find(i,x-1,a[x].q)+find(x+1,j,a[x].q)+s[j]-s[i-1]); 53 f[i,j,w]:=min(f[i,j,w],find(i,x-1,w)+find(x+1,j,w)+s[j]-s[i-1]+k); 54 end; 55 exit(f[i,j,w]); 56 end; 57 //================== 58 procedure main; 59 begin 60 fillchar(f,sizeof(f),255); 61 writeln(find(1,n,0)); 62 end; 63 //================== 64 begin 65 assign(input,'treapmod.in'); reset(input); 66 assign(output,'treapmod.out'); rewrite(output); 67 read(n,k); 68 for i:=1 to n do read(a[i].s); 69 for i:=1 to n do read(a[i].q); 70 for i:=1 to n do read(a[i].f); 71 sort(1,n,1); 72 for i:=1 to n do a[i].q:=i; 73 sort(1,n,2); 74 for i:=1 to n do s[i]:=s[i-1]+a[i].f; 75 main; 76 close(input); close(output); 77 end.