//By Ralif Rakhmatullin
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
#include<math.h>
#include<cassert>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<bitset>
#include<valarray>
#include<iterator>
#include<list>
#define ll long long
#define ull unsigned long long
#define mp make_pair
#define S second
#define ld long double
#define F first
#define y1 LOL
#define ld long double
#define pb push_back
#define len length
#define sz size    
#define beg begin
const ll INF = (ll)1e18 + 123;
const int inf=(int)2e9 + 123; 
const int mod=1e9+7;
using namespace std;
int n, p[200011];
vector<pair<int, int> > ans;
pair<int, int> t[2][1000011];
pair<int, int> minim(pair<int, int> x, pair<int, int> y){
	if(x.F < y.F)
		return x;
	return y;
}
void build(int v = 1, int tl = 1, int tr = n){
	t[1][v] = t[0][v] = mp(inf, 0);
	if(tl == tr)
		return;
	int tm = (tl + tr) / 2;
	build(v * 2, tl, tm);
	build(v * 2 + 1, tm + 1, tr);
}
void upd(int type, int pos, int x, int v = 1, int tl = 1, int tr = n){
	if(tl == tr){
		t[type][v] = mp(x, pos);
		return;
	}
	int tm = (tl + tr) / 2;
	if(pos <= tm)
		upd(type, pos, x, v * 2, tl, tm);
	else
		upd(type, pos, x, v * 2 + 1, tm + 1, tr);
	t[type][v] = minim(t[type][v * 2], t[type][v * 2 + 1]);
}
pair<int, int> get(int type, int l, int r, int v = 1, int tl = 1, int tr = n){
	if(tl > r || tr < l || l > r)
		return mp(inf, 0);
	if(tl >= l && tr <= r)
		return t[type][v];
	int tm = (tl + tr) / 2;
	return minim(get(type, l, r, v * 2, tl, tm), get(type, l, r, v * 2 + 1, tm + 1, tr));
}
pair<int, int> solve(int l, int r){
	if(l >= r)
		return mp(inf, inf);
	int si = l % 2;
	pair<int, int> L = get(si, l, r);
	pair<int, int> R = get((si ^ 1), L.S + 1, r);
//	cout << l << " - " << r << " : " << L.S << " " << R.S << endl;
	if(L.F == inf || R.F == inf){
		return mp(inf, inf);    
	}
	upd(si, L.S, inf);
	upd((si ^ 1), R.S, inf);
	return mp(L.S, R.S);
//	solve(l, L.S - 1);
//	solve(L.S + 1, R.S - 1);
//	solve(R.S + 1, r);
}                                   
struct st{
	int l, r, pl, pr;     
	st(){
		l = r = 0;
		pl = pr = 0;
	}                     
	st(int a, int b, int c, int d){
		l = a;
		r = b;
		pl = c;
		pr = d;
	}
	bool operator < (const st &a) const
	{
		return p[l] > p[a.l];
	}                  
};
priority_queue<st> q;   
int main(){
	unsigned int FOR;
 	asm("rdtsc" : "=A"(FOR));
  	srand(FOR);
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	//cout.tie(0);
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	cin >> n;
	build();
	for(int i = 1; i <= n; i ++){
		cin >> p[i];
		upd(i % 2, i, p[i]);
	}
	pair<int, int> a = solve(1, n);                
	q.push(st(a.F, a.S, 1, n));
	while(q.sz()){
		st x = q.top();
		q.pop();
		int l = x.l, r = x.r, pl = x.pl, pr = x.pr;
	//	cout << l << " " << r << " " << pl << " " << pr << endl;
		if(l > r)
			continue;
		ans.pb(mp(l, r));
		pair<int, int> y;
		if(l - 1 > pl){
			y = solve(pl, l - 1);
			q.push(st(y.F, y.S, pl, l - 1));
		}
		if(r - l > 1){
			y = solve(l + 1, r - 1);
			q.push(st(y.F, y.S, l + 1, r - 1));
		}
		if(r + 1 < pr){
			y = solve(r + 1, pr);
			q.push(st(y.F, y.S, r + 1, pr));
		}
	}	              
	for(int i = 0; i < ans.sz(); i ++){
		cout << p[ans[i].F] << " " << p[ans[i].S] << " ";
	}
	return 0;
}

Measured memory_bytes: 17396