题解 AVL 树
Description
给出一个 \(n\) 个点的 AVL 树,求保留 \(k\) 个点使得字典序最小。
\(n\le 5\times 10^5\)
Solution
因为我很 sb ,所以只会 \(\Theta(n\log^2n)\)。
首先可以注意到的是,树高是 \(\Theta(\log n)\) 的,然后我们要让字典序最小的话,可以考虑一个点一个点加进入判断是否可以。
我们考虑设 \(f_{u,i}\) 表示以 \(u\) 为根的子树在当前已选的点的情况下保留深度为 \(i\) 的还需选的最小点数。那么对于我们当前考虑的点,如果已经加入的点数加上还需加入的最小点数 \(\le k\) 那么我们就可以加入这个点。
发现这个 \(f\) 每次会改变的只会有 \(\text{rt}\to u\) 这一条路径(\(u\) 是当前考虑的点),所以我们就可以做到 \(\Theta(n\log^2 n)\) 了。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 500005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n,K,rt,num,ans[MAXN],ls[MAXN],rs[MAXN],h[MAXN],f[MAXN],hei[MAXN],dp[MAXN][25];
void dfs1 (int u){
if (ls[u]) dfs1 (ls[u]);
if (rs[u]) dfs1 (rs[u]);
hei[u] = max (hei[ls[u]],hei[rs[u]]) + 1;
}
int tot,pos[25],reh[25],sta[25][25];
void ins (int root,int x){
++ tot,pos[tot] = root,reh[tot] = h[root];
for (Int i = 0;i <= hei[root];++ i) sta[tot][i] = dp[root][i];
if (root == x){
h[x] = max (h[ls[x]],h[rs[x]]) + 1,memset (dp[x],0x3f,sizeof (dp[x]));
for (Int i = h[x];i <= hei[x];++ i)
chkmin (dp[x][i],dp[ls[x]][i - 1] + dp[rs[x]][i - 1]),
chkmin (dp[x][i],dp[ls[x]][i - 2] + dp[rs[x]][i - 1]),
chkmin (dp[x][i],dp[ls[x]][i - 1] + dp[rs[x]][i - 2]);
return ;
}
else{
if (x < root) ins (ls[root],x);else ins (rs[root],x);
h[root] = max (h[ls[root]],h[rs[root]]) + 1,memset (dp[root],0x3f,sizeof (dp[root]));
for (Int i = h[root];i <= hei[root];++ i)
chkmin (dp[root][i],dp[ls[root]][i - 1] + dp[rs[root]][i - 1] + (root > x)),
chkmin (dp[root][i],dp[ls[root]][i - 2] + dp[rs[root]][i - 1] + (root > x)),
chkmin (dp[root][i],dp[ls[root]][i - 1] + dp[rs[root]][i - 2] + (root > x));
}
}
signed main(){
freopen ("avl.in","r",stdin);
freopen ("avl.out","w",stdout);
read (n,K);
for (Int i = 1;i <= n;++ i){
int p;read (p);
if (p == -1) rt = i;
else if (i < p) ls[p] = i;
else rs[p] = i;
}
dfs1 (rt),f[1] = 1,f[2] = 2;
for (Int i = 3;i <= 25;++ i) f[i] = f[i - 1] + f[i - 2] + 1;
memset (dp,0x3f,sizeof (dp));
for (Int u = 0;u <= n;++ u)
for (Int i = 0;i <= hei[u];++ i) dp[u][i] = f[i];
for (Int i = 1;i <= n;++ i){
tot = 0,ins (rt,i);
if (num + 1 + dp[rt][h[rt]] > K){
for (Int i = 1;i <= tot;++ i){
int now = pos[i];
h[now] = reh[i];for (Int k = 0;k <= hei[now];++ k) dp[now][k] = sta[i][k];
}
}
else ans[i] = 1,num ++;
}
for (Int i = 1;i <= n;++ i) putchar (ans[i] + '0');putchar ('\n');
return 0;
}
题解 AVL 树的更多相关文章
- PAT甲级题解-1123. Is It a Complete AVL Tree (30)-AVL树+满二叉树
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6806292.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- PAT甲级题解-1066. Root of AVL Tree (25)-AVL树模板题
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6803291.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- 算法与数据结构(十一) 平衡二叉树(AVL树)
今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...
- AVL树原理及实现(C语言实现以及Java语言实现)
欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好 ...
- AVL树
AVL树 在二叉查找树(BST)中,频繁的插入操作可能会让树的性能发生退化,因此,需要加入一些平衡操作,使树的高度达到理想的O(logn),这就是AVL树出现的背景.注意,AVL树的起名来源于两个发明 ...
- AVL树的平衡算法(JAVA实现)
1.概念: AVL树本质上还是一个二叉搜索树,不过比二叉搜索树多了一个平衡条件:每个节点的左右子树的高度差不大于1. 二叉树的应用是为了弥补链表的查询效率问题,但是极端情况下,二叉搜索树会无限接近 ...
- 【数据结构】平衡二叉树—AVL树
(百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...
- 数据结构图文解析之:AVL树详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构之平衡二叉树(AVL树)
平衡二叉树(AVL树)定义如下:平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树: (1)它的左子树和右子树的高度之差绝对值不超过1: (2)它的左子树和右子树都是平衡二叉树. AVL树避免了 ...
随机推荐
- ES6扩展——箭头函数
1.箭头函数 在es6中,单一参数的单行箭头函数语法结构可以总结如下: const 函数名 = 传入的参数 => 函数返回的内容,因此针对于 const pop = arr => arr. ...
- 理解Java中对象基础Object类
一.Object简述 源码注释:Object类是所有类层级关系的Root节点,作为所有类的超类,包括数组也实现了该类的方法,注意这里说的很明确,指类层面. 所以在Java中有一句常说的话,一切皆对象, ...
- 学习小计: Kaggle Learn Time Series Modeling
ARIMA模型,参数含义参考:https://www.cnblogs.com/bradleon/p/6827109.html from statsmodels.tsa.arima_model impo ...
- ROS入门学习(基于Ubuntu16.04+kinetic)
本文主要部分全部来源于ROS官网的Tutorials. Setup roscore # making sure that we have roscore running rosrun turtlesi ...
- Python - 面向对象编程 - 小实战(3)
需求 房子(House)有户型.总面积.家具名称列表:新房子没有任何的家具 家具(HouseItem)有名字.占地面积 席梦思(bed) 占地 4 平米 衣柜(bed) 占地 2 平米 餐桌(bed) ...
- scikit-learn 1.0 版本新特性及变动前瞻性预览
1 简介 就在几天前,著名的机器学习框架scikit-learn在pypi上释放了其1.0rc1版本,这里给大家科普一下,版本号中的rc是Release Candidate的简称,代表当前的版本是一个 ...
- 用 Java 写个塔防游戏「GitHub 热点速览 v.21.37」
作者:HelloGitHub-小鱼干 本周 GitHub Trending 的主题词是:多语言.本周特推的 C 语言教程是大家都知道的阮一峰编写的,想必和他之前的技术文章类似,能起到科普作用.再来时 ...
- 查询同一张表符合条件的某些数据的id拼接成一个字段返回
同一张表存在类似多级菜单的上下级关系的数据,查询出符合条件的某些数据的id拼接成一个字段返回: SELECT CONCAT(a.pid, ',', b.subid) AS studentIDS FRO ...
- Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用
原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...
- Java 扫描识别条形码图片
1.条形码扫描识别的实现方法及步骤 本文以Java代码示例介绍如何来扫描和识别条形码图片.这里使用免费条码工具 Free Spire.Barcode for Java,调用BarcodeScanner ...