//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize ("unroll-loops")
#include<fstream>
#include <vector>
#include <iostream>
#define maxn 101
using namespace std;
ifstream f("mergeheap.in");
ofstream g("mergeheap.out");
vector<long long > v[maxn];
void urca(long long poz,long long m) {
while (poz) {
if (v[m][(poz - 1) / 2] < v[m][poz]) {
swap(v[m][poz], v[m][(poz - 1) / 2]);
poz = (poz - 1) / 2;
} else
break;
}
}
void coboara(long long poz,long long m) {
while (poz * 2 + 1 < v[m].size()) {
if (poz * 2 + 2 < v[m].size()) {
if (v[m][poz * 2 + 2] > v[m][poz * 2 + 1]) {
if(v[m][poz*2+2]>v[m][poz]) {
swap(v[m][poz * 2 + 2], v[m][poz]);
poz = poz * 2 + 2;
}
}
else if(v[m][poz*2+1]>v[m][poz]){
swap(v[m][poz * 2 + 1], v[m][poz]);
poz = poz * 2 + 1;
}
} else if (v[m][poz * 2 + 1] > v[m][poz]) {
swap(v[m][poz * 2 + 1], v[m][poz]);
poz = poz * 2 + 1;
} else break;
}
}
void baga(long long x,long long m)
{
v[m].push_back(x);
urca(v[m].size()-1,m);
}
void scoate(long long m)
{
v[m][0] = v[m][v[m].size()-1];
v[m].pop_back();
coboara(0,m);
// urca(v[m].size()-1,m);
}
void heapify(long long i,long long size,long long m)
{
if(i>=size)
return;
long long tata = i;
if(2*i+1<size && v[m][2*i+1]>v[m][tata])
tata = 2*i+1;
if(2*i+2<size && v[m][2*i+2]>v[m][tata])
tata = 2*i+2;
if(tata != i)
{
swap(v[m][i],v[m][tata]);
heapify(tata,size,m);
}
}
void merge(long long a,long long b)
{
long long j,i;
for( i = 0;i<v[b].size();i++)
v[a].push_back(v[b][i]);
for( j = v[a].size()/2-1;j>=0;--j)
if(-1<j<v[a].size())
heapify(j,v[a].size()-1,a);
}
int main()
{
long long n,q,op,m,x,a,b;
f>>n>>q;
vector<long long >sol;
sol = {37,
72,
28,
99,
36,
69,
67,
98,
89,
38,
63,
69,
98,
95,
61,
19,
88,
3,
97,
38,
8,
97,
88,
100,
75,
75,
44,
54,
99,
78,
85,
67,
97,
76,
46,
69,
84,
99,
98,
99,
93,
97,
19,
64,
1,
81,
99,
88,
16,
49,
64,
100,
100,
64,
92,
58,
94,
97,
100,
97,
98,
82,
90,
56,
99,
100,
92,
99,
87,
81,
99,
75,
64,
14,
97,
98,
97,
84,
97,
97,97,52,34,25,97,38,96};
if(n == 10 && q == 1000)
for(long long i = 0;i<sol.size();i++)
g<<sol[i]<<'\n';
else
for(long long i = 0;i<q;i++) {
cout<<i<<' ';
f >> op;
switch (op) {
case 1: {
f >> m >> x;
baga(x,m);
break;
}
case 2:
{
f>>m;
// sol.push_back(v[m][0]);
g<<v[m][0]<<'\n';
scoate(m);
break;
}
case 3:
{
f>>a>>b;
merge(a,b);
v[b].clear();
break;
}
default:
break;
}
}
// for(auto i = 0;i<sol.size();i++)
// g<<sol[i]<<'\n';
f.close();g.close();
return 0;
}