L2-012. 关于堆的判断
今天看项目partner在操练这道天梯赛的题目,他是用stl做的,我之前都不知道stl_heap这个东西,学习了一下受益匪浅。将这道曾经做过,但是是copy书上代码还扣了1份的题重新找出来认真做了一遍。现在ac了发blog上来分享一下
关键字:用stl_heap方法建堆
将一系列给定数字顺序插入一个初始为空的小顶堆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代码
/*
Name:L2-012. 关于堆的判断
Author: spencercjh
Date:2017年11月14日16:01:27
Description:GPLT团体程序设计天梯赛-练习集
reference:stl_heap:https://www.cnblogs.com/coderyoyo/archive/2011/01/21/stl_heap.html
key word:stl_vector,stl_heap
*/
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<functional>
#include<numeric>
#include<stack>
using namespace std;
int main() {
int N,M;
scanf("%d %d",&N,&M);
vector<int> heap;
for(int i=0; i<N; i++) {
int t;
scanf("%d",&t);
heap.push_back(t);
make_heap(heap.begin(),heap.end(),greater<int>());
}
for(int i=0; i<M; i++) {
int x,y;
char cmd[20],tmp[20];
scanf("%d%s",&x,cmd);
if(cmd[0]=='a') {
//A和B是不是兄弟节点即判断A和B的父亲节点相不相等
scanf("%d%s%s",&y,cmd,tmp);
int index_x=-distance(find(heap.begin(),heap.end(),x),heap.begin());
int index_y=-distance(find(heap.begin(),heap.end(),y),heap.begin());
if((index_x+1)/2==(index_y+1)/2) {
printf("T\n");
} else {
printf("F\n");
}
} else {
scanf("%s%s",tmp,cmd);
if(cmd[0]=='r') {
//A 是不是堆的根
if(x==heap[0]) {
printf("T\n");
} else {
printf("F\n");
}
} else if(cmd[0]=='p') {
//A是不是B的父节点
scanf("%s%d",tmp,&y);
int index_x=-distance(find(heap.begin(),heap.end(),x),heap.begin());
int index_y=-distance(find(heap.begin(),heap.end(),y),heap.begin());
if(2*index_x+1==index_y||2*index_x+2==index_y) {
printf("T\n");
} else {
printf("F\n");
}
} else if(cmd[0]=='c') {
//A是不是B的孩子节点
scanf("%s%d",tmp,&y);
int index_x=-distance(find(heap.begin(),heap.end(),x),heap.begin());
int index_y=-distance(find(heap.begin(),heap.end(),y),heap.begin());
if(2*index_y+1==index_x||2*index_y+2==index_x) {
printf("T\n");
} else {
printf("F\n");
}
}
}
}
}
参考学习stl_heap
reference:https://www.cnblogs.com/coderyoyo/archive/2011/01/21/stl_heap.html
STL_heap在本题中的使用
make_heap(iterator,iterator,cmp);(好把这不是源码这是我自己编的),使用这个方法能将一个普通的vector变成一个小/大根堆,让这个vector和你学堆heap的时候那个数组一样,这样就懂了吧?关于儿子父亲的那些判断,什么left child=2i+1,right child=2i+2,father=i/2等等操作都是一样的。
总结
本来C风格的先建堆,再实现逻辑的一套代码要100多行,现在50几行,嘻嘻你懂的,美滋滋。