问题描述

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

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

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

一个结点在树中的深度定义为它到树根的距离加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

说明

【样例说明】

输入的原图是左图,它的访问代价是: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。

解析

可以发现,题目所给的意思就是构造了一棵Treap。由于数据值是不会变的,所以根据平衡树的性质,中序遍历也是不会改变的。另外,中序遍历中的一段区间对应着树上的一棵子树,所以,我们可以利用区间DP的思想以及子树根节点的权值是子树中最小的这个性质,得出如下状态:

设\(f[i][j][k]\)表示中序遍历中区间\([i,j]\)得到一棵树且最小权值大于等于k的最小代价。枚举子树的根节点x,如果x的权值小于k,就需要修改权值。我们有如下状态转移方程:

\[f[i][j][k]=min(f[i][x-1][k]+f[x+1][j][k],f[i][x-1][w[x]]+f[x+1][j][w[x]]+K)
\]

同时,因为根节点两边的子树深度均加1,所以需要再加上i到j的频率之和。

另外,每个点的权值可以直接离散化为1到n,不影响答案。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 72
using namespace std;
struct node{
int dat,w,f;
}a[N];
int n,m,i,j,k,l,x,val[N],sum[N],f[N][N][N];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
int my_comp(const node &x,const node &y)
{
return x.dat<y.dat;
}
int main()
{
n=read();m=read();
for(i=1;i<=n;i++) a[i].dat=read();
for(i=1;i<=n;i++){
a[i].w=read();
val[i]=a[i].w;
}
for(i=1;i<=n;i++) a[i].f=read();
sort(val+1,val+n+1);
sort(a+1,a+n+1,my_comp);
int n1=unique(val+1,val+n+1)-val-1;
for(i=1;i<=n;i++){
a[i].w=lower_bound(val+1,val+n1+1,a[i].w)-val;
sum[i]=sum[i-1]+a[i].f;
}
memset(f,0x3f,sizeof(f));
for(i=1;i<=n+1;i++){
for(k=1;k<=n;k++) f[i][i-1][k]=0;
}
for(l=1;l<=n;l++){
for(i=1;i+l-1<=n;i++){
j=i+l-1;
for(k=1;k<=n;k++){
for(x=i;x<=j;x++){
f[i][j][k]=min(f[i][j][k],f[i][x-1][k]+f[x+1][j][k]+m+sum[j]-sum[i-1]);
if(a[x].w>=k) f[i][j][k]=min(f[i][j][k],f[i][x-1][a[x].w]+f[x+1][j][a[x].w]+sum[j]-sum[i-1]);
}
}
}
}
printf("%d\n",f[1][n][1]);
return 0;
}

反思

并没有注意到这是一个Treap,即使知道了也没有注意到中序遍历不变的性质。所以,多多关注特殊条件特殊性质。

[洛谷P1864] NOI2009 二叉查找树的更多相关文章

  1. 洛谷$P1864\ [NOI2009]$二叉查找树 区间$dp$

    正解:区间$dp$ 解题报告: 传送门$QwQ$ 首先根据二叉查找树的定义可知,数据确定了,这棵树的中序遍历就已经改变了,唯一能改变的就是通过改变权值从而改变结点的深度. 发现这里权值的值没有意义,所 ...

  2. P1864 [NOI2009]二叉查找树

    链接P1864 [NOI2009]二叉查找树 这题还是蛮难的--是我菜. 题目描述中的一大堆其实就是在描述\(treap.\),考虑\(treap\)的一些性质: 首先不管怎么转,中序遍历是确定的,所 ...

  3. 不失一般性和快捷性地判定决策单调(洛谷P1912 [NOI2009]诗人小G)(动态规划,决策单调性,单调队列)

    洛谷题目传送门 闲话 看完洛谷larryzhong巨佬的题解,蒟蒻一脸懵逼 如果哪年NOI(放心我这样的蒟蒻是去不了的)又来个决策单调性优化DP,那蒟蒻是不是会看都看不出来直接爆\(0\)?! 还是要 ...

  4. 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告

    P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...

  5. 洛谷 [P1963] [NOI2009] 变换序列

    这是一道二分图匹配的题 先%dalao博客 建图并没有什么难的,但是关键在于如何使字典序最小. 一个很显然的想法是先求出一个完美匹配,然后从x集合的第一个元素开始,如果该元素匹配的较小的一个,那么继续 ...

  6. 洛谷P1963 [NOI2009]变换序列(二分图)

    传送门 我可能真的只会网络流……二分图的题一点都做不来…… 首先每个位置有两种取值,所以建一个二分图,只要有完美匹配就说明有解 考虑一下每一个位置,分别让它选择两种取值,如果都不能形成完美匹配,说明无 ...

  7. 洛谷P1912 [NOI2009]诗人小G(决策单调性)

    传送门 题解 决策单调性是个啥……导函数是个啥……这题解讲的是啥……我是个啥…… //minamoto #include<iostream> #include<cstdio> ...

  8. Luogu P1864 [NOI2009]二叉查找树

    题目 \(v\)表示权值,\(F\)表示频率. 首先我们显然可以把这个权值离散化. 然后我们想一下,这个东西它是一棵树对吧,但是我们改变权值会引起其树形态的改变,这样很不好做,所以我们考虑把它转化为序 ...

  9. 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...

随机推荐

  1. Windows环境下Mysql 5.7读写分离简单记录

    一.目的 本文记录了在Windows环境中,mysql数据库读写分离配置过程. 二.准备: Master机器:Windows 10 虚拟机,IP:192.168.3.32 Slave机器:Window ...

  2. OpenStack Nova 高性能虚拟机之 NUMA 架构亲和

    目录 文章目录 目录 写在前面 计算平台体系结构 SMP 对称多处理结构 NUMA 非统一内存访问结构 MPP 大规模并行处理结构 Linux 上的 NUMA 基本对象概念 NUMA 调度策略 获取宿 ...

  3. 一文学会Rust?

    Rust是什么 Rust 是一个系统编程语言,它注重三个方面:安全,速度和并发性. 特征: 1.没有垃圾回收机制,没有运行时,效率超过c++,直逼c语言 2.内存安全,并发安全,没有空指针 3.极其丰 ...

  4. django连接数据库的类型

    字段类型 django的models里面字段类型除了上面的常用的 models.CharField和models.IntegerField,还有更多的类型 1.models.AutoField 自增列 ...

  5. 【ABAP系列】SAP ABAP 的替代和校验

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 的替代和校验 ...

  6. Redis进阶:Redis的主从复制机制

    Redis进阶:Redis的主从复制机制 主从复制机制介绍 单机版的Redis存在性能瓶颈,Redis通过提高主从复制实现读写分离,提高了了Redis的可用性,另一方便也能实现数据在多个Redis直接 ...

  7. 【转】sql server数据收集和监控

    转自:https://www.cnblogs.com/zhijianliutang/p/4476403.html 相关系列: https://www.cnblogs.com/zhijianliutan ...

  8. JS案例经验1

    一 可以通过设置在一个div中的多个div的定位属性为absolute,从而使得这几个元素重叠.他们都脱离了标准流. 二 对于absolute的left和right属性,当left和right同时出现 ...

  9. Thinkphp3.2 Redis缓存session

    Thinkphpsession缓存没有redis类库 Redis.class.php放在Library/Think/Session/Driver/下: <?php /** * +-------- ...

  10. 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1333275 这个题不是很 ...