输入样例1:
6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 21 -1 4
15 22 -1 -1
5 35 -1 -1
输出样例1:
YES
输入样例2:
6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 11 -1 4
15 22 -1 -1
50 35 -1 -1
输出样例2:
NO
#include <bits/stdc++.h>
using namespace std;
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
struct Node{
int k1,k2,lchild,rchild;
}CartTree[1005];
bool flag=true;
void IsCart(int root,int min_k1,int max_k1){
if(root==-1)return;
int k1=CartTree[root].k1;
int k2=CartTree[root].k2;
int lchild=CartTree[root].lchild;
int rchild=CartTree[root].rchild;
if(k1>max_k1||k1<min_k1){
flag=false;
return;
}
if(lchild!=-1){
if(CartTree[lchild].k2<=k2){
flag=false;
return;
}
}
if(rchild!=-1){
if(CartTree[rchild].k2<=k2){
flag=false;
return;
}
}
IsCart(lchild,min_k1,k1-1);
IsCart(rchild,k1+1,max_k1);
}
int main()
{
int n,root;
cin>>n;
for(int i=0;i<n;i++){
cin>>CartTree[i].k1>>CartTree[i].k2>>CartTree[i].lchild>>CartTree[i].rchild;
}
int Label[1500];
memset(Label,0,n*sizeof(int));
for(int i=0;i<n;i++){
if(CartTree[i].lchild!=-1)Label[CartTree[i].lchild]=1;
if(CartTree[i].rchild!=-1)Label[CartTree[i].rchild]=1;
}
for(int i=0;i<n;i++){
if(!Label[i]){
root=i;
break;
}
}
IsCart(root,INT_MIN,INT_MAX);
if(flag)cout<<"YES\n";
else cout<<"NO\n";
return 0;
}
借鉴了以下链接的大佬代码
一、定义
笛卡尔树 - OI Wiki (oi-wiki.org)https://oi-wiki.org/ds/cartesian-tree/笛卡尔树是一种二叉树,每一个结点由一个键值二元组 (k,w)构成。要求 k满足二叉搜索树的性质,而 w 满足堆的性质。一个有趣的事实是,如果笛卡尔树的 k ,w键值确定,且 k互不相同, w互不相同,那么这个笛卡尔树的结构是唯一的。
二、解题步骤
本题通过数组存储了待检测树,子节点通过lchild,rchild与父节点关联
先将节点信息按照结点编号0--n-1录入数组
一、找根节点
树最重要的是寻找根节点:根节点特点是,它不是任何一个节点的左右孩子
遂建立新数组初始化为0,凡是在任何结点的左右孩子出现过的结点,将此数组对应编号均置为1,遍历此数组,其他结点全是1,只有根节点不是1;遂找出
二、判断是否笛卡尔树
k1判断二叉搜索树利用递归:利用父节点的k1键值控制此结点k1键值范围
左子树在(min_k1,k1-1]
右子树在[k1+1,max_k1)
k2判断最小堆:判断左右孩子是否都大于此节点
如果左右孩子有一个不大于,false 停止