#include<cstdio>
#include<string>
#include<iostream>
#include<vector>
#include <algorithm>//fill()在里面
#include <cmath>
#include<queue>
#include<unordered_set>
#include<set>
#include<map>
#include<unordered_map>
#include <cstdlib>//貌似是free,malloc等函数的头文件:含有NULL
using namespace std;
//A1147
const int INF=1e9; //fill(map[0],map[0]+maxn*maxn,INF);
const int maxn=10010;
//给一个树的层序遍历:判断其是不是堆:是大根堆还是小跟堆
//树是完全二叉树,所以可以用数组来表示树结构:下标可以表示双亲和孩子关系
int m,n;//查询的树的个数以及每棵树的节点个数
vector<int> v;
vector<int> post;
//递归参数:index :根节点
void postOrder(int index){
if(index>n)return ;
postOrder(index*2);
postOrder(index*2+1);
post.push_back(v[index]);//先存之后再输出方便判断输出格式
}
int main(){
//根据v[0]和v[1]的大小判断大顶(flag=1)还是小顶(flag=-1),flag=0:不是堆
scanf("%d %d",&m,&n);
v.resize(n);//转换为n的大小,方便之后用下标:节点从1开始存
while(m--){
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
int flag=v[1]>v[2]?1:-1;
//在有n个节点的完全二叉树中:最后一个分支节点的下标是 n/2
for(int i=1;i<=(n/2);i++){
//判断分支节点的孩子符不符合flag的条件
int left=i*2;
int right=i*2+1;//右孩子节点可能会不存在
if(flag==1){ //大根堆
//判断当前的左右孩子节点是否符合:不符合直接flag=0:后面直接判断输出不是堆就行
if(v[left]>v[i] || (right<=n && v[right]>v[i])){
flag=0;
break;
}
}
if(flag==-1){
//小根堆
if(v[left]<v[i] || (right<=n && v[right]<v[i])){
flag=0;
break;
}
}
}
if(flag==0)printf("Not Heap\n");
else printf("%s Heap\n",flag==1?"Max":"Min");
postOrder(1);
//输出post里的序列
for(int i=0;i<post.size();i++){
if(i!=0)printf(" ");
printf("%d",post[i]);
}
printf("\n");
post.clear();
}
return 0;
}