抓住完全二叉树的性质:某个节点编号为
i
d
id
id,左儿子为
2
∗
i
d
2*id
2∗id,右儿子为
2
∗
i
d
+
1
2*id+1
2∗id+1
利用这条性质可以精准定位到节点的左右儿子
之后正常进行大小根堆的判断和后序遍历即可
Tip所有树上的操作,最关键的是确定结构,即确定左右儿子
换句话说,只要我们能够确定儿子,就可以对树直接进行操作,建树就变得无关紧要了
#include#include #include #include using namespace std; const int N = 1010; int t[N]; int ans[N], cnt = 0; int n; void dfs(int i) { int lc = i * 2; int rc = i * 2 + 1; if (lc <= n) dfs(lc); if (rc <= n) dfs(rc); ans[++cnt] = t[i]; } int main() { int T; scanf("%d%d", &T, &n); while (T--) { for (int i = 1; i <= n; ++i) scanf("%d",&t[i]); int flag = 0; cnt = 0; for (int i = 1; 2 * i <= n; ++i) { if (2 * i + 1 <= n) { if (t[i] >= t[i * 2] && t[i] >= t[i * 2 + 1]) { if (flag >= 0) flag = 1; else { flag = 0; break; } } else if (t[i] <= t[i * 2] && t[i] <= t[i * 2 + 1]) { if (flag <= 0) flag = -1; else { flag = 0; break; } } else { flag = 0; break; } } else { if (t[i] >= t[i * 2]) { if (flag >= 0) flag = 1; else { flag = 0; break; } } else if (t[i] <= t[i * 2]) { if (flag <= 0) flag = -1; else { flag = 0; break; } } else { flag = 0; break; } } } if (flag == 0) printf("Not Heapn"); else if (flag > 0) printf("Max Heapn"); else printf("Min Heapn"); dfs(1); for (int i = 1; i <= n; ++i) { printf("%d", ans[i]); if (i < n) printf(" "); } printf("n"); } return 0; }
1115 Counting Nodes in a Binary Search Tree
二叉搜索树(不带旋转操作)的建立,还是比较容易的
对于每个节点记录深度deep,最后输出时按照deep统计一下即可
#include#include #include #include using namespace std; const int N = 1010; int n, cnt = 0; int mxdeep; struct node { int x; int lc; int rc; int deep; }; node T[N]; void insert(int i, int x) { if (x <= T[i].x) { if (T[i].lc != -1) insert(T[i].lc, x); else { T[i].lc = ++cnt; T[cnt].x = x; T[cnt].lc = T[cnt].rc = -1; T[cnt].deep = T[i].deep + 1; mxdeep = max(mxdeep, T[cnt].deep); return; } } else { if (T[i].rc != -1) insert(T[i].rc, x); else { T[i].rc = ++cnt; T[cnt].x = x; T[cnt].lc = T[cnt].rc = -1; T[cnt].deep = T[i].deep + 1; mxdeep = max(mxdeep, T[cnt].deep); return; } } } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { int x; scanf("%d", &x); if (i == 1) { T[1].x = x; T[1].lc = T[1].rc = -1; T[1].deep = 1; mxdeep = 1; cnt = 1; } else insert(1,x); } int n1 = 0; int n2 = 0; for (int i = 1; i <= cnt; ++i) { if (T[i].deep == mxdeep) n1++; if (T[i].deep == mxdeep - 1) n2++; } printf("%d + %d = %d", n1, n2, n1 + n2); return 0; }
1167 Cartesian Tree
不要被题目描述吓住了
题目给出了一个小根二叉树的中序遍历
根节点必然是子树中序遍历中最小的那个节点
确定了根节点,自然就划分出左右子树,进行递归建树即可
最后bfs输出层次遍历即可
Tip感觉序列建树的关键是划分左右子树
前序+中序,后序+中序,前序+二叉搜索树,中序+小(大)根堆
以上情况都可以确定唯一树结构
#include#include #include #include using namespace std; const int N = 40; int n, cnt = 1; int a[N]; struct node { int num; int lc; int rc; }; node T[N]; void build(int x,int l,int r) { int index = l; for (int i = l; i <= r; ++i) if (a[i] < a[index]) index = i; T[x].num = a[index]; T[x].lc = T[x].rc = -1; if (index > l) { T[x].lc = ++cnt; build(cnt, l, index - 1); } if (index < r) { T[x].rc = ++cnt; build(cnt, index + 1, r); } } int Q[N * 2]; void bfs() { int tou = 0; int wei = 0; Q[++wei] = 1; while (tou < wei) { int index = Q[++tou]; if (T[index].lc != -1) Q[++wei] = T[index].lc; if (T[index].rc != -1) Q[++wei] = T[index].rc; } } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); build(1,1,n); bfs(); for (int i = 1; i <= n; ++i) { printf("%d", T[Q[i]].num); if (i < n) printf(" "); } return 0; }



