题意
给定一个元素个数为 n n n的序列 a a a,这个序列是一棵树宽度优先遍历得来的。这棵树有几个特点:根的编号为 1 1 1、任意节点的孩子结点的编号依次递增、任意两个节点的编号不相同。现在要求所有满足要求的树的最小高度。
数据范围
1
≤
T
≤
1000
1 \leq T \leq 1000
1≤T≤1000
2
≤
n
≤
2
∗
1
0
5
2 \leq n \leq 2*10^5
2≤n≤2∗105
1
≤
a
i
≤
n
;
a
i
≠
a
j
;
a
1
=
1
1\leq a_i\leq n; a_i≠a_j; a_1=1
1≤ai≤n;ai=aj;a1=1
∑
n
≤
2
∗
1
0
5
\sum n \leq 2*10^5
∑n≤2∗105
思路
这里的贪心性质很容易发现,就是如果当前遍历到的数可以放在这一层的话,那它就不会放在下一层,这一点证明非常容易。
根据这个性质,我们就可以很容易的将树建立出来。存放一下上一层的空闲节点(指还没有孩子节点的节点),同时存放当前层已经有多少节点了,然后维护上一个数以及答案。这题就可以在
O
(
n
)
O(n)
O(n)的时间复杂度下做完了。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--){
int n, ans = 0;
scanf("%d",&n);
int root;
scanf("%d",&root);
int last = root;
int num = 0, tmp = 0;
for(int i=2;i<=n;i++){
int x;
scanf("%d",&x);
if(last>x){
if(num==0) ans ++, num = tmp - 1, tmp = 1;
else num --, tmp ++;
}
else tmp ++;
last = x;
}
printf("%d\n",ans+1);
}
return 0;
}