#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_poizcy.hpp>
typedef long long  ll;
#define pb                push_back
#define mp                make_pair
#define all(a)            (a).begin(), (a).end()
#define mem(a,h)          memset(a, (h), sizeof(a))
#define fi first
#define se second
#define por(a,b) (((a%MOD) * (b%MOD))%MOD)
#define forg(i, b, e, c)    for (ll i = (ll)b; i < (ll)e; i+=c)
#define forr(i, b, e)    for (ll i = b; i < e; i++)
 
 
using namespace std;
//using namespace __gnu_pbds;
typedef double lldb;
typedef pair<int, int>  ii;
typedef pair<double, double>  iidb;
#define iii pair<ii, nodo*>
typedef vector<ll>     vi;
typedef vector<vi>     vvi;
typedef vector<ii>      vii;
typedef vector<ll>      vll;
//typedef tree<ii,null_type,less<ii>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
const ll INF = 1e9+7;
const double PI = acos(-1);
#define initseg ll new_nodo=(pnodo*2),mid=(iz+der)/2;
 
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define tam 1001000
#define offset 3000
#define ptr nodo*


using namespace std;
struct nodo
{
	ptr iz;ptr der;ptr mid;
	ii valor;	
};
nodo nodos[tam];int cuniv=0;
ptr getnodo()
{
	return &nodos[cuniv++];
}

int v[tam],n;const int cmplog=18;

	int sp[2][cmplog][tam];int lstsparce[tam];
	void initsp()
	{
		forr(par,0,2)
			forr(bit,0,cmplog)
				forr(pos,0,tam)
				sp[par][bit][pos]=INF;
		forr(i,0,2)
		{
			forg(j,i,n,2)
			{
				sp[i][0][j]=v[j];
			}
		/*	<<"par "<<i<<endl;
			forr(j,0,n+3)
			{
				<<sp[i][0][j]<<" ";
			}
			<<endl;*/
		}
		forr(par,0,2)
		{
			forr(bit,1,cmplog)
			{
				forr(pos,0,n)
				{
					sp[par][bit][pos]=min(sp[par][bit-1][pos],sp[par][bit-1][pos+(1<<(bit-1))]);
				}
				/*<<"par "<<par<<endl;
				forr(j,0,n+3)
				{
					<<sp[par][bit][j]<<" ";
				}
				<<endl;*/
			}
			//<<endl;
		}
		lstsparce[1]=0;
		forr(i,2,tam)
		lstsparce[i]=lstsparce[i/2]+1;
	}
	int getquery(int iz,int der)
	{
		int par=(iz%2);
		int delta=(der-iz+1);
		int bit=lstsparce[delta];
		return min(sp[par][bit][iz],sp[par][bit][der-(1<<bit)+1]);
	}
int vpos[tam];
void divide(ptr nodo,int iz,int der)
{
	if (iz>der)
		return ;
	//<<iz<<' '<<der<<endl;
	assert((der-iz+1)%2==0);

	if (der-iz+1==2)
	{
		nodo->valor={v[iz],v[der]};
		return;
	}
	int li=vpos[getquery(iz,der)];
	int ri=vpos[getquery(li+1,der)];
	//<<li<<' '<<ri<<endl;
	nodo->valor={v[li],v[ri]};

	nodo->iz=getnodo();
	nodo->iz->valor={-1,-1};
	nodo->mid=getnodo();
	nodo->mid->valor={-1,-1};
	nodo->der=getnodo();
	nodo->der->valor={-1,-1};
	divide(nodo->iz,iz,li-1);
	divide(nodo->mid,li+1,ri-1);
	divide(nodo->der,ri+1,der);
}

int main()
{
	
	forr(i,0,tam)
		nodos[i].iz=nodos[i].der=nodos[i].mid=NULL;

	
	cin>>n;
	forr(i,0,n)
	{
		cin>>v[i];
		vpos[v[i]]=i;

	}
	initsp();	
	ptr root;
	priority_queue<iii,vector<iii>,greater<iii> > cola;
	

	root=getnodo();
	divide(root,0,n-1);
	//return 0;
	cola.push({root->valor,root});
	while(!cola.empty())
	{
		auto par=cola.top();
		cola.pop();
		ptr cual=par.se;
		cout<<par.fi.fi<<' '<<par.fi.se<<' ';
		if (cual->iz && cual->iz->valor.fi!=-1)
			cola.push({cual->iz->valor,cual->iz});

		if (cual->mid && cual->mid->valor.fi!=-1)
			cola.push({cual->mid->valor,cual->mid});

		if (cual->der && cual->der->valor.fi!=-1)
			cola.push({	cual->der->valor,cual->der});
	}
}

Measured memory_bytes: 188896