#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <deque>
#include <complex>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <ctime>
#include <iterator>
#include <bitset>
#include <numeric>
#include <list>
#include <iomanip>
#include <cassert>

#if __cplusplus >= 201103L
#include <array>
#include <tuple>
#include <initializer_list>
#include <unordered_set>
#include <unordered_map>
#include <forward_list>

#define cauto const auto&
#define ALL(v) begin(v),end(v)
#else
#define ALL(v) (v).begin(),(v).end()
#endif

using namespace std;


namespace{
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;

#define VV(T) vector<vector< T > >

template <class T>
void initvv(vector<vector<T> > &v, int a, int b, const T &t = T()){
	v.assign(a, vector<T>(b, t));
}
template <class T> inline T &chmin(T &x, const T &y){ return x = min(x, y); }
template <class T> inline T &chmax(T &x, const T &y){ return x = max(x, y); }
template <class F, class T>
void convert(const F &f, T &t){
	stringstream ss;
	ss << f;
	ss >> t;
}


#define REP(i,n) for(int i=0;i<int(n);++i)
#define RALL(v) (v).rbegin(),(v).rend()


#define MOD 1000000007LL
#define EPS 1e-8


template <class DatTp, class Comp = std::less<DatTp> >
struct static_rmq{
	typedef unsigned long long ull;
	typedef unsigned size_type;

	std::vector<DatTp> data;
	Comp cmp;
	std::vector<std::vector<size_type> > sp_rmq;
	std::vector<ull> bl_tort;

	explicit static_rmq(const Comp &comp = Comp()) : cmp(comp) {}

	template <class Iter>
	static_rmq(Iter beg, Iter en, const Comp &comp = Comp()) : cmp(comp) {
		init(beg, en);
	}

	template <class Iter>
	void init(Iter beg, Iter en){
		sp_rmq.clear();
		bl_tort.clear();
		data.assign(beg, en);
		size_type sz = size();
		if(!sz){ return; }

		size_type sp_len = sz / 64;
		sp_rmq.reserve(64 - __builtin_clzll(sp_len | 1));

		std::vector<size_type> vec(sp_len);
		for(size_type i = 0; i < sp_len; ++i){
			size_type t = i * 64;
			for(size_type j = t + 1; j < (i + 1) * 64; ++j){
				t = minidx(t, j);
			}
			vec[i] = t;
		}
		sp_rmq.push_back(vec);

		for(size_type i = 1; (1u << i) <= sp_len; ++i){
			vec.clear();
			size_type r = (1u << (i - 1));
			std::vector<size_type> &prv = sp_rmq.back();
			for(size_type j = 0; j + r * 2 <= sp_len; ++j){
				vec.push_back(minidx(prv[j], prv[j + r]));
			}
			sp_rmq.push_back(vec);
		}

		bl_tort.assign(sz, 0ull);
		std::vector<size_type> st;
		st.reserve(64);
		for(size_type low = 0; low < sz; low += 64){
			size_type high = std::min<size_type>(low + 64, sz);
			ull val = 0;
			st.clear();
			for(size_type j = high; j-- != low; ){
				while(!st.empty()){
					size_type tp = st.back();
					if(cmp(data[tp], data[j])){ break; }
					val ^= 1ull << (tp % 64);
					st.pop_back();
				}
				st.push_back(j);
				val |= 1ull << (j % 64);
				bl_tort[j] = val;
			}
		}
	}

	size_type size() const{ return data.size(); }

	size_type minidx(size_type i, size_type j) const{
		if(i > j){ std::swap(i, j); }
		// if(j >= size()){ return i; }
		return !cmp(data[j], data[i]) ? i : j;
	}

	const DatTp& operator[] (size_type i) const{
		return data[i];
	}

	// [lt, rt]
	size_type operator() (size_type lt, size_type rt) const{
		if(lt > rt){ return lt; }
		size_type bl_lt = lt / 64, bl_rt = rt / 64;
		size_type ret;
		ull rtmask = ((2ull << (rt % 64)) - 1);
		if(bl_lt == bl_rt){
			ull bit = bl_tort[lt] & rtmask;
			size_type k = 63 - __builtin_clzll(bit);
			ret = bl_lt * 64 + k;
		}
		else{
			ret = bl_lt * 64 + 63 - __builtin_clzll(bl_tort[lt]);
			if(bl_lt + 1 != bl_rt){
				size_type numblk = bl_rt - bl_lt - 1;
				size_type k = 63 - __builtin_clzll(numblk);
				size_type cand1 = sp_rmq[k][bl_lt + 1];
				ret = minidx(ret, cand1);
				if((1u << k) != numblk){
					size_type cand2 = sp_rmq[k][bl_rt - (1u << k)];
					ret = minidx(ret, cand2);
				}
			}
			size_type cand3 = bl_rt * 64 + 63 - __builtin_clzll(bl_tort[bl_rt * 64] & rtmask);
			ret = minidx(ret, cand3);
		}
		return ret;
	}
};

typedef tuple<int,int,int,int> ti4;

vector<int> p;
priority_queue<ti4> pq;
static_rmq<int> rmqodd, rmqeven;
vector<int> inv;

void add(int lt, int rt){
	if(lt > rt){ return; }
	int idx1 = (lt & 1 ? rmqodd : rmqeven)(lt, rt - 1);
	int idx2 = (rt & 1 ? rmqodd : rmqeven)(idx1 + 1, rt);
	pq.emplace(-p[idx1], -p[idx2], lt, rt);
}

void mainmain(){
	int n;
	scanf("%d", &n);
	
	inv.assign(n + 1, -1);
	p.resize(n);
	vector<int> podd(n, n + 10), peven(n, n + 10);
	for(int i = 0; i < n; ++i){
		int a;
		scanf("%d", &a);
		p[i] = a;
		(i & 1 ? podd : peven)[i] = a;
		inv[a] = i;
	}
	
	rmqodd.init(ALL(podd));
	rmqeven.init(ALL(peven));
	
	add(0, n - 1);

	vector<int> ans;
	while(!pq.empty()){
		int elem1, elem2, lt, rt;
		tie(elem1, elem2, lt, rt) = pq.top();
		pq.pop();
		elem1 = -elem1;
		elem2 = -elem2;
		ans.push_back(elem1);
		ans.push_back(elem2);

		int idx1 = inv[elem1];
		int idx2 = inv[elem2];
		add(lt, idx1 - 1);
		add(idx1 + 1, idx2 - 1);
		add(idx2 + 1, rt);
	}
	
	const char *spl = "";
	for(int x : ans){
		printf("%s%d", spl, x);
		spl = " ";
	}
	puts("");
}



}
int main() try{
//	ios::sync_with_stdio(false); cin.tie(0);
	cout << fixed << setprecision(10);
	cerr << fixed << setprecision(4);
	mainmain();
}
catch(...){}


Measured memory_bytes: 11136