D. Minimal Height Tree(ranting 1600)超详细题解
前言
本系列的意义在于两点,一则是作为本人(一个编程初学者)的学习笔记记录,二则希望能对后来者提供一些帮助,因为本人也为新手,难免有些错误或讲述不清之处,恳请大家指出或提出建议,本人也会虚心修改。
本系列的目标是帮助大家解决一些codeforces上,ranting1600+(或者之后会改为1300+,看博主水平吧)的题目
一、题目及翻译
1. 原题(贴图)
2. 翻译
- 机翻版
- 省流版
给出一个序列(按bfs算法访问节点的顺序给出,其中每个点都只被访问了一次且每个顶点的所有子节点都是按升序被查看的),让我们构建一棵最小高度树(树的高度是树顶点的最大深度,顶点的深度是从根到它的叶子节点的长度)
二、解析及AC代码
1.解析
我们需要先讨论一下本题的贪心思想,对于每个点,由于每个顶点的所有子节点都是按升序被查看的,所以如果序列出现升序,接到当前子树的根节点,就好,但是如果序列出现降序,我们就只有两种选择,1.把树加一层,2.把这个点接到当前子树的根节点的兄弟节点上去。为了使高度最小,我们肯定尽量选择第二个方法来处理,除非所有兄弟节点都已经被接过了,我们才选择第一种方法
那么如果我们记录每层有多少个节点来做,肯定是可行的,但这里提供一种更简单的思路。我们用一个cnt来记录当前节点应对应连接在哪个节点上,如果a[i] < a[i - 1] ,我们就把cnt+1,这样就能自动对齐上层节点了
那么,此时同学们就可以自己去尝试一下了,如果还是不太理解,可以参考下博主下面的AC代码
2.AC代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<unordered_map>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 2e5 + 10, M = 1e6 + 10, MAXI = 0x3f3f3f3f;
int n, m, t, res;
int a[N];
int tree[N];//记录当前节点的深度
int find()
{
int cnt = 0;//cnt是表明当前节点应对应连接在哪个节点
tree[1] = 0;
for (int i = 1 + 1; i <= n; i++)
{
if (a[i] < a[i - 1] || i == 2)
cnt++;
tree[i] = tree[cnt] + 1;
}
return tree[n];
}
int main()
{
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
res = find();
cout << res << endl;
}
return 0;
}
如果觉得有用还请点个赞吧,拜托拜托