二叉查找树

【题目描述】

已知一棵特殊的二叉查找树。根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小。

另一方面,这棵查找树中每个结点都有一个权值,每个结点的权值都比它的儿子结点的权值要小。

已知树中所有结点的数据值各不相同;所有结点的权值也各不相同。这时可得出这样一个有趣的结论:如果能够确定树中每个结点的数据值和权值,那么树的形态便可以唯一确定。因为这样的一棵树可以看成是按照权值从小到大顺序插入结点所得到的、按照数据值排序的二叉查找树。

一个结点在树中的深度定义为它到树根的距离加1。因此树的根结点的深度为1。

每个结点除了数据值和权值以外,还有一个访问频度。我们定义一个结点在树中的访问代价为它的访问频度乘以它在树中的深度。整棵树的访问代价定义为所有结点在树中的访问代价之和。

现在给定每个结点的数据值、权值和访问频度,你可以根据需要修改某些结点的权值,但每次修改你会付出K的额外修改代价。你可以把结点的权值改为任何实数,但是修改后所有结点的权值必须仍保持互不相同。现在你要解决的问题是,整棵树的访问代价与额外修改代价的和最小是多少?

【输入格式】

输入文件中的第一行为两个正整数N,K。其中:N表示结点的个数,K表示每次修改所需的额外修改代价。

接下来的一行为N个非负整数,表示每个结点的数据值。

再接下来的一行为N个非负整数,表示每个结点的权值。

再接下来的一行为N个非负整数,表示每个结点的访问频度。

其中:所有的数据值、权值、访问频度均不超过400000。每两个数之间都有一个空格分隔,且行尾没有空格。

【输出格式】

输出文件中仅一行为一个数,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值。

【样例输入】

4 10

1 2 3 4

1 2 3 4

1 2 3 4

【样例输出】

29

分析:

参加比赛遇到的题目,比赛时看到题目感觉是用树型dp,但一直没有思路,只好用近似模拟的方法乱搞的,后来看了题解才会做......

首先我们知道该树是一颗特殊的二叉排序树,它比普通的多一个优先级(在本题中就是权值),使它有了堆的性质。如果没有修改操作,我们可以根据这些性质构造一颗这样的树然后模拟,而本题的难度就在修改,对此可以用动规解决。

定义f[i,j,w]为第i..j的节点构成节点权值大于w的子树遍历的最小代价,a[i,1]保存节点的数据值,a[i,2]保存节点离散化后的权值,a[i,3]保存节点的访问频度,s[i,j]为第i..j的节点访问频度之和。

离散化权值,就是将权值按从小到大排序后用其在数组中编号来表示其权值,之所以能这样做是因为节点权值各部相同,而每个点权值数字本身多少没有意义,重要的是它与其它节点权值相比的大小关系,离散化后就可以将大小参差不齐的数字按大小的关系转换为有序的编号,可以节省空间,也可省去动规中的一些麻烦的东西。

分两种情况

在i..j中枚举根节点k

若不修改,条件是k的权值>=w,则f[i,j,w]:=max(f[i,j,w],f[i,k-1,a[k,2]]+f[k+1,j,a[k,2]]+s[i,j])

若修改,则f[i,j,w]:=max(f[i,j,w],f[i,k-1,w]+f[k+1,j,w]+s[i,j]+k)

解释:如果不修改,k必须在子树中,其左右孩子权值均要大于k的权值;如果将k修改为根节点,其左右孩子权值可比w大很小很小的一个数字。

代码

program treap;
var
f:array[..,..,..]of longint;
a:array[..,..]of longint;
s:array[..,..]of longint;
n,i,m,j,w,k:longint;
function min(x,y:longint):longint;
begin
if x<y then min:=x else min:=y;
end;
procedure sort(x:longint);
var i,j,t:longint;
begin
for i:= to n- do
for j:=i+ to n do
if a[x,i]>a[x,j] then
begin
t:=a[,i]; a[,i]:=a[,j]; a[,j]:=t;
t:=a[,i]; a[,i]:=a[,j]; a[,j]:=t;
t:=a[,i]; a[,i]:=a[,j]; a[,j]:=t;
end;
end;
begin
assign(input,'treap.in');
reset(input);
assign(output,'treap.out');
rewrite(output);
readln(n,m);
for i:= to n do
read(a[,i]); readln;
for i:= to n do
read(a[,i]); readln;
for i:= to n do
read(a[,i]);
sort();
for i:= to n do
a[,i]:=i;
sort();
for i:= to n do
for j:=i to n do
s[i,j]:=s[i,j-]+a[,j];
for i:= to n do
for j:= to n do
for w:= to n do
f[i,j,w]:=maxlongint div ;
for i:= to n+ do
for w:= to n do
f[i,i-,w]:=;
for w:=n downto do
for i:=n downto do
for j:=i to n do
for k:=i to j do
if i=j then
if a[,k]>=w then f[i,j,w]:=a[,k] else f[i,j,w]:=a[,k]+m
else begin
if a[,k]>=w then f[i,j,w]:=min(f[i,j,w],f[i,k-,a[,k]]+f[k+,j,a[,k]]+s[i,j]);
f[i,j,w]:=min(f[i,j,w],f[i,k-,w]+f[k+,j,w]+s[i,j]+m);
end;
writeln(f[,n,]);
close(input); close(output);
end.

BZOJ 1564 :[NOI2009]二叉查找树(树型DP)的更多相关文章

  1. bzoj 1564 [NOI2009]二叉查找树(树形DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1564 [题意] 给定一个Treap,总代价为深度*距离之和.可以每次以K的代价修改权值 ...

  2. BZOJ 1564: [NOI2009]二叉查找树( dp )

    树的中序遍历是唯一的. 按照数据值处理出中序遍历后, dp(l, r, v)表示[l, r]组成的树, 树的所有节点的权值≥v的最小代价(离散化权值). 枚举m为根(p表示访问频率): 修改m的权值 ...

  3. bzoj 1564 [NOI2009]二叉查找树 区间DP

    [NOI2009]二叉查找树 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 906  Solved: 630[Submit][Status][Discu ...

  4. BZOJ 1564: [NOI2009]二叉查找树

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1564 Description Input Output 只有一个数字,即你所能得到的整棵树的访 ...

  5. BZOJ 2286 消耗战 - 虚树 + 树型dp

    传送门 题目大意: 每次给出k个特殊点,回答将这些特殊点与根节点断开至少需要多少代价. 题目分析: 虚树入门 + 树型dp: 刚刚学习完虚树(好文),就来这道入门题签个到. 虚树就是将树中的一些关键点 ...

  6. BZOJ 1509 逃学的小孩 - 树型dp

    传送门 题目大意: 在一棵树中, 每条边都有一个长度值, 现要求在树中选择 3 个点 X.Y. Z , 满足 X 到 Y 的距离不大于 X 到 Z 的距离, 且 X 到 Y 的距离与 Y 到 Z 的距 ...

  7. BZOJ 1864 三色二叉树 - 树型dp

    传送门 题目大意: 给一颗二叉树染色红绿蓝,父亲和儿子颜色必须不同,两个儿子颜色必须不同,问最多和最少能染多少个绿色的. 题目分析: 裸的树型dp:\(dp[u][col][type]\)表示u节点染 ...

  8. POJ3659 Cell Phone Network(树上最小支配集:树型DP)

    题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...

  9. POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断

    好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...

随机推荐

  1. 【BZOJ1257】[CQOI2007] 余数之和(数学题)

    点此看题面 大致题意: 求\(\sum_{i=1}^nk\%i\). 关于除法分块 这是一道除法分块的简单应用题. 式子转换 显然\(k\%i\)是一个很难处理的项. 于是我们就要使用使用一个常用的套 ...

  2. wu2198:难得的波段抄底机会

    很好的波段抄底机会 个人浅见看,目前染料股跌出的机会明显,养殖股波段机会明显,芯片.半导体.集成电路.北导.软件.国产操作系统等科技股短线机会不错.另外,大盘指数2856/2806区域的波段操作机会不 ...

  3. python __getattr__ __setattr__

    class Rectangle: def __init__(self): self.width = 0 self.height = 0 def __setattr__(self, key, value ...

  4. CUDA && GPU中dim3介绍

  5. Python中的集合set

    >>> help(set) Help on class set in module __builtin__: class set(object) | set(iterable) -- ...

  6. Bootstrap历练实例:响应式导航(带有表单)

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  7. 关于Runtime Issues

    前言:在使用某移动直播的SDK的时候发现,在Run应用的时候会有紫色的警告(Xcode9 + iOS11) 当时还专门提交了工单,当时对方的回复是,大概意思是不影响使用,后期修复. 今天看视频发现这是 ...

  8. 操作系统(3)_CPU调度_李善平ppt

    不只上面的四种,比如时间片到了也会引起调度. 具体的调度算法: fcfs简单,但是波动很大. 最高相应比算法,执行时间最长就应该等待的长点,比sjf多了一个等待时间的考虑. 硬件定时器和软件计数器共同 ...

  9. 记录一下CSS outline-width 属性

    outline(轮廓)是绘制于元素周围的一条线,位于边框边缘的外围. outline-width指定轮廓的宽度. 注意: 请始终在outline-width属性之前声明outline-style属性. ...

  10. POJ 2406 Power String

    算出next数组. 对于任何一个循环字串,len-next[len]必为最小循环节长度 若len%(len-next[len])==0 即为循环字串,n=len/(len-next[len]) 否则输 ...