题解 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树避免了 ...
随机推荐
- div 居中显示
<html lang="en"> <head> <meta charset="UTF-8"> <title>di ...
- 在Excel中怎样才能在某一行前面一次插入多行?
你在要插入的行以下选中多少行,点插入,就能插入多少行.
- MySQL 常用的聚合函数
[常用的聚合函数] mysql聚合函数一般用户统计一列值进行计算,然后返回计算结果.一般于分组group by 配合使用. count //统计个数 select count(*) from test ...
- 【SpringMVC】文件上传与下载、拦截器、异常处理器
文件下载 使用ResponseEntity实现下载文件的功能 index.html <!DOCTYPE html> <html lang="en" xmlns:t ...
- MongoDB(4)- Collection 集合相关
Collection MongoDB 将文档存储在集合中 集合存储在 Database 中 集合类似于关系数据库(Mysql)中的表 如果集合不存在,则 MongoDB 会在第一次存储该集合数据时创建 ...
- 10分钟学会VS NuGet包私有化部署
前言 我们之前实现了打包发布NuGet,但是发布后的引用是公有的,谁都可以访问,显然这种方式是不可取的. 命令版本:10分钟学会Visual Studio将自己创建的类库打包到NuGet进行引用(ne ...
- 硕盟SM-A44|USB3.0转RJ45千兆网口转换器(TYPE A USB3.0 TO RJ45)
硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.,转换USB端口到以太网端口.它让你投入低成本就可以轻松拥有千兆以太网.可将网络连接到台式机,笔记本电脑等等设备.硕盟 USB千兆网卡采用嵌 ...
- weblogic漏洞分析之CVE-2017-10271
weblogic漏洞分析之CVE-2017-10271 一.环境搭建 1)配置docker 这里使用vulhub的环境:CVE-2017-10271 编辑docker-compose.yml文件,加入 ...
- xshell与小键盘问题
有些程序员的键盘是带有小数字键的,在使用xshell中文版时就可能出现一些小状况,本集就同大家分析一下使用数字键盘出现乱码的情况怎么办. 图1:使用数字小键盘出现乱码 问题描述: 在xshell上用v ...
- kubectl apply部署时可以用 --record 方便记录版本 和回退
1.部署时正常时下面的 kubectl apply -f http.yaml 2.如果修改文件文件重新部署或者之前有上一个版本的 想回退上一个的 可以无感知的回退回去 不影响业务 其中http-de ...