【NOIP2014模拟10.30】二叉查找树
Description
二叉查找树是二叉树,每个结点最多只有两个孩子结点。每个结点都有一个整数权值val。如果某个结点的权值是X,那么她的左子树的结点权值都小于X,右子树的结点权值都大于X。
现在要通过依次插入N个整数构造出二叉查找树,每个整数范围【1,N】,且都不相同,即要插入的序列是一个排列。第一个被插入的整数作为树根结点root,接下来依次插入剩下的N-1个整数,每次插入一个整数就相当于执行函数:insert(X, root),其中insert(X, root)递归过程如下:
insert( number X, node now )
{
计数器C 加1
if 待插入的整数X小于结点now的权值 then
{
if 结点now无左孩子 then
新建一个权值为X的结点,并设置为now的左孩子
else insert(X, now的左孩子)
}
else
{
if 结点now无右孩子 then
新建一个权值为X的结点,并设置为now的右孩子
else insert(X, now的右孩子)
}
}
其中:计数器C是全局变量,初始值是0。
Input
第一行,一个整数 N (1 ≤ N ≤ 300000)。
接下来有N行,每行一个整数,每个整数的范围是[1, N],且所有待插入的整数都不相同。
Output
共N行,每行以一个整数,第i行输出的结果表示的意义是:把第i个整数插入到查找二叉树后,计数器C的值是多少。
Sample Input
输入1:
4
1
2
3
4
输入2:
5
3
2
4
1
5
输入3:
8
3
5
1
6
8
7
2
4
Sample Output
输出1:
0
1
3
6
输出2:
0
1
2
4
6
输出3:
0
1
2
4
7
11
13
15
题目大意
建一个二分查找树,每一次插入新的元素时,输出在这之前所有的深度(也就是ans+=d[i])
思路
显然按照题目描述打50分肯定是有的哩,之后呢我们就会发现,一个数它的深度应该是它爸爸的深度+1(废话),但是它的爸爸呢很显然,要不是比它大的数中最小的数(前驱),就是比它小的数中最大的数(后继)。结果呢就可以得到d[i]=max(d[前驱],d[后继])+1。
那么就比较轻松 ,这个呢用双向链表,线段树都是可以的,但是呢,双向链表不会,线段树也只会简单的,结果导致这个半个月前的水 题,拖到现在。忍无可忍,无需再忍!“好像可以搞平衡树哦”,“平衡树?学学”,结果。。。懂了是懂了,但是他们的那个代码,真心自闭啊。“set不就是用红黑树的嘛”,“对哟,set!”,结果一整天都在学指针和迭代器,心里苦。
不过好歹会了嘛,起码会用了什么lower_bound之类的。
还是说两嘴迭代器吧。
迭代器
迭代器是今天才正式涉及的,说的不精准还请见谅,大概嘛,跟指针差不多,就我的理解,应该是储存一个数的地址,那要它干什么呢,比如像等会用的set,里面的lower_bound(x)就是指在集合里找到>=x的最小的数的迭代器,(啊,好绕啊,就是地址,我就是这么理解的),好了像定义之类的等会到程序里再说。
上代码
#include<cstdio>
#include<iostream>
#include<set>
#define N 300007
using namespace std;
long long n,ans,d[N],a[N];//保险起见longlong,d为深度
int main(){
scanf("%lld",&n);
scanf("%lld",&a[1]);//先将第一个数输进来,方便点
printf("0\n");//第一个输出必定是0
set<long long>A;
A.insert(a[1]);//将a[1]放进集合
d[a[1]]=0;//注意是a[1]这个值的深度,不是1的深度。
for(int i=2;i<=n;i++){
scanf("%lld",&a[i]);
set<long long>::iterator A1,A2;//好了这里就是定义一个迭代器了,类型::iterator 变量名
A1=A.lower_bound(a[i]);//跟上面说的一样
A2=A1;//这个时候它们都是后继(如果a[i]有后继的话)
if(A1!=A.begin()) A1--;
if(A2==A.end()) A2--;
//A1为前驱,A2为后继。若A1为第一个数的地址的话,那么说明没有前驱,若A2为end(),说明没有找到,也就是没有后继
d[a[i]]=max(d[*A2],d[*A1])+1;//疑问为什么有*号,因为A1,A2是迭代器,是地址,要想调用地址上的值,就要加上*
ans+=d[a[i]];
printf("%lld\n",ans);
A.insert(a[i]);//一定放下面,因为迭代器会自动更新的
}
}