将一系列给定数字顺序插入一个初始为空的小顶堆H[]
。随后判断一系列相关命题是否为真。命题分下列几种:
x is the root
:x
是根结点;x and y are siblings
:x
和y
是兄弟结点;x is the parent of y
:x
是y
的父结点;x is a child of y
:x
是y
的一个子结点。
输入格式:
每组测试第1行包含2个正整数N
(≤ 1000)和M
(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N
个要被插入一个初始为空的小顶堆的整数。之后M
行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
输出格式:
对输入的每个命题,如果其为真,则在一行中输出T
,否则输出F
。
输入样例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
输出样例:
F
T
F
T
AC代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define int long long //可能会超时
#define PII pair<int,int>
const int INF = 0x3f3f3f3f, mod = 998244353;
const int N = 1005;
int heap[N], n, m;
int cnt;
void down(int u) {
int t = u;
if (u * 2 <= cnt && heap[u * 2] < heap[t]) t = u * 2;
if (u * 2 + 1 <= cnt && heap[u * 2 + 1] < heap[t]) t = u * 2 + 1;
if (t - u) {
swap(heap[t], heap[u]);
down(t);
}
}
void up(int u) {
while (u / 2 && heap[u / 2] > heap[u]) {
swap(heap[u / 2], heap[u]);
u /= 2;
}
}
signed main()
{
ios::sync_with_stdio, cin.tie(0), cout.tie(0);
cin >> n >> m;
getchar();
while (n--) {
int x;
cin >> x;
getchar();
heap[++cnt] = x;
up(cnt);
}
while (m--) {
string s;
getline(cin, s);
if (s.back() == 's') {
string first, second;
for (int i = 0;i < s.size();i++) {
if (s[i] == ' ') break;
first += s[i];
}
int d = 0;
for (int i = 0;i < s.size();i++) {
if (s[i] == 'd') d = i;
}
for (int i = d + 2;s[i] != 'a';i++) second += s[i];
int f1 = stoi(first), f2 = stoi(second),f11,f22;
for (int i = 1;i <= cnt;i++) {
if (f1 == heap[i]) f11 = i;
if (f2 == heap[i]) f22 = i;
}
if ((f11 - f22 == 1 && f11 & 1) || (f22 - f11 == 1 && f22 & 1)) puts("T");
else puts("F");
}
else if (s.back() == 't') {
string first;
for (int i = 0;i < s.size();i++) {
if (s[i] == ' ') break;
first += s[i];
}
int x = stoi(first);
if (heap[1] == x) puts("T");
else puts("F");
}
else {
int flag = 0;
for (auto i : s) {
if (i == 'p') {
flag = 1;
break;
}
}
if (flag) {
string first, second;
for (int i = 0;i < s.size();i++) {
if (s[i] == ' ') break;
first += s[i];
}
for (int i = s.size() - 1;i >= 0;i--) {
if (s[i] == ' ') break;
second += s[i];
}
reverse(second.begin(), second.end());
int x = stoi(first), y = stoi(second);
int x1, y1;
for (int i = 1;i <= cnt;i++) {
if (heap[i] == x) x1 = i;
if (heap[i] == y) y1 = i;
}
x1 == y1 / 2 ? puts("T") : puts("F");
}
else {
string first, second;
for (int i = 0;i < s.size();i++) {
if (s[i] == ' ') break;
first += s[i];
}
for (int i = s.size() - 1;i >= 0;i--) {
if (s[i] == ' ') break;
second += s[i];
}
reverse(second.begin(), second.end());
int x = stoi(first), y = stoi(second);
int x1, y1;
for (int i = 1;i <= cnt;i++) {
if (heap[i] == x) x1 = i;
if (heap[i] == y) y1 = i;
}
if (x1 == y1 * 2 || x1 == y1 * 2 + 1) puts("T");
else puts("F");
}
}
}
return 0;
}
题意不难理解,从定义出发,用一个一维数组heap存堆的所有元素,判断是否是根结点只需判断x是否等于heap[1]即可。判断兄弟结点通过找规律可发现,x和y是兄弟结点当且仅当x和y在堆中对应的下标差值为1且奇数大。判断父结点和子结点类似,判断对应下标是否等于x/2或x*2或x*2+1。
(趁这几天没事把一直不怎么懂的堆学了,算是了结一桩心事吧。。。)