题意
将一系列给定数字顺序插人一个初始为空的最小堆 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的一个子结点。
Input
每组测试第1行包含2个正整数N(≤1000)和M(≤20),分别是插入元素的个数以及需要判断的命题数;
下一行给出区间[-10 000, 10 000]内的N个要被插人一个初始为空的小顶堆的整数;
之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
Output
对输入的每个命题,如果为真,则在一行中输出T,否则输出F。
思路
首先建堆,然后对每个判断语句找到其在堆中的位置,判断对应的是否成立。
建堆:输入的时候进行调整,因为题目要求最小堆,所以将该节点和父节点比较,如果该节点小于父节点的话就将该节点向上调整,这样最后的数组就满足最小堆的性质啦。
性质:
x的父节点为x/2,子节点为2x,2x+1
判断语句:
首先编写函数get(x)表示得到x在堆里的下标,当然也可以提前用map预处理下。
x is the root,判断x在堆里的下标是否为1
x and y are siblings:判断x和y在堆里的下标的父节点是否相同
x is the parent of y:判断y在堆的下标/2是否为x
x is a child of y:判断x在堆里的下标/2是否为y
代码
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7; #define debug(x) cout<<#x<<":"<<x<<endl; int n,m,a[maxn]; int get(int x){ for(int i=1;i<=n;i++) if(a[i]==x) return i; return -1; } int main() { cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; int now=i; while(now>1&&a[now]<a[now/2]){ swap(a[now],a[now/2]); now/=2; } } /// for(int i=1;i<=n;i++) cout<<a[i]<<" "; /// puts(""); while(m--){ int x,y;string s; cin>>x>>s; if(s=="and"){ ///x and y are siblings:x和y是兄弟结点。 cin>>y; cin>>s;cin>>s; if(get(x)/2==get(y)/2) puts("T"); else puts("F"); } else{ cin>>s; if(s=="a"){ ///x is a child of y:x是y的一个子结点 cin>>s;cin>>s;cin>>y; if(get(x)/2==get(y)) puts("T"); else puts("F"); } else{ cin>>s; if(s=="root"){ if(get(x)==1) puts("T"); else puts("F"); } else{ cin>>s>>y; if(get(y)/2==get(x)) puts("T"); else puts("F"); } } } } return 0; }