写在前面:看到这个题,感觉并不难。算是模板题。不过翻看了一下网上的题解,基本上全是常规的建立一个二叉搜索树,建立一个小顶堆(也可以用优先队列)。然后分别遍历判断。当然,我比较懒,就没去建树建堆。
思路:首先建立结构体数组来存储每个节点的k1,k2,左右孩子编号。然后在接受数据的时候,用一个前驱数组pre[]来存储每个结点的前驱结点,不仅可以用这个数组找到根还可以用它遍历判断,这样就可以不用建树建堆了。。哈哈哈哈。。具体操作如下:
1.首先遍历一遍pre,如果那个值是-1,说明它是根。
2.判断小顶堆:遍历pre数组 只要判断这个结点是不是比它前驱结点的k2值大就行了。
3.判断二叉搜素树:同样用pre数组来遍历,只不过要用到DFS来进行一次中序遍历,因为二叉搜索树中序遍历序列是一个递增的序列,这样只用判断这个序列是不是每个数都比后面数小就行。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,pre[1010];
vector<int>v;
struct node
{
int k1,k2,left,right,id;
}p[1010];
void read()
{
memset(pre,-1,sizeof pre);
cin>>n;
for(int i=0;i<n;i++)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
p[i].k1=a; p[i].k2=b;
p[i].left=c; p[i].right=d; p[i].id=i;
if(c!=-1) pre[c]=i;
if(d!=-1) pre[d]=i;
}
}
void dfs(int num)
{
if(num==-1) return ;
else
{
dfs(p[num].left);
v.push_back(p[num].k1);
dfs(p[num].right);
}
}
bool check2()
{
int t=-1,flag=1;
for(int i=0;i<n;i++)
if(pre[i]==-1)
{
t=i;
break;
}
dfs(t);
for(int i=0;i<n-1;i++)
if(v[i]>v[i+1])
{
flag=0;
break;
}
if(flag) return true;
return false;
}
bool check1()
{
for(int i=0;i<n;i++)
{
if(pre[i]==-1) continue;
if(p[i].k2<p[pre[i]].k2) return false;
}
return true;
}
int main()
{
read();
if(check1()&&check2()) cout<<"YES";
else cout<<"NO";
}