#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <cassert>
#include <queue>
#include <ctime>
#include <string>
#include <cstring>
#include <random>
#define mp make_pair
#define pb push_back
#define NAME ""
#define y1 y1_423
#define list lista

using namespace std;

typedef long long ll;
typedef long double ld;

template<typename T>
ostream& operator << (ostream& cout, const vector<T> &a) {
	if ((int)a.size() == 0) {
		return (cout << "()");
	}
	cout << "(" << a[0];
	for (int i = 1; i < (int)a.size(); i++) {
		cout << "; " << a[i];
	}
	return (cout << ")");
}

template<typename T>
ostream& operator << (ostream& cout, const set<T> &a) {
	if ((int)a.size() == 0) {
		return (cout << "{}");
	}
	auto it = a.begin();
	cout << "{" << *it;
	++it;
	for (; it != a.end(); ++it) {
		cout << "; " << *it;
	}
	return (cout << "}");
}

template<typename T>
ostream& operator << (ostream& cout, const multiset<T> &a) {
	if ((int)a.size() == 0) {
		return (cout << "{}");
	}
	auto it = a.begin();
	cout << "{" << *it;
	++it;
	for (; it != a.end(); ++it) {
		cout << "; " << *it;
	}
	return (cout << "}");
}

template<typename T1, typename T2>
ostream& operator << (ostream& cout, const pair<T1, T2> &a) {
	return cout << "(" << a.first << "; " << a.second << ")";
}

random_device gen;
mt19937 rnd(gen());

const int nmax = 2000 * 1000;
const int inf = 2000 * 1000 * 1000;
const ll infl = 1000ll * 1000ll * 1000ll * 1000ll * 1000ll * 1000ll;
const int mod = 1000 * 1000 * 1000 + 7;
const ld pi = acos(-1.0);

struct node {
	int x, y, z;
	node(){}
	node(int X, int Y, int Z) {
		x = X;
		y = Y;
		z = Z;
	}
};

bool operator < (node a, node b) {
	return (mp(a.x, mp(a.y, a.z)) < mp(b.x, mp(b.y, b.z)));
}

int rmq[2][nmax], a[2][nmax], q[nmax], s, n, top = 1;
pair<int, int> answer[nmax];
int par[nmax];
set<node> nowa;
vector<int> go[nmax];

int ask(int z, int ind, int l1, int r1, int l, int r) {
	if (l1 > r || l > r1) {
		return -1;
	}
	if (l <= l1 && r1 <= r) {
		return rmq[z][ind];
	}
	int ind1 = ask(z, ind * 2, l1, (l1 + r1) / 2, l, r);
	int ind2 = ask(z, ind * 2 + 1, (l1 + r1) / 2 + 1, r1, l, r);
	if (ind1 == -1) return ind2;
	else if (ind2 == -1) return ind1;
	else return (a[z][ind1] > a[z][ind2] ? ind2 : ind1);
}

void get(int l, int r, int lvl, int p = -1) {
	if (l > r) return;
	int ind = ask(l & 1, 1, 0, s - 1, l, r) - s;
	int ind1 = ask((l & 1) ^ 1, 1, 0, s - 1, ind, r) - s;
	answer[lvl] = mp(q[ind], q[ind1]);
	go[lvl].pb(++top);
	get(l, ind - 1, top, lvl);
	go[lvl].pb(++top);
	get(ind + 1, ind1 - 1, top, lvl);
	go[lvl].pb(++top);
	get(ind1 + 1, r, top, lvl);
}

int main() {
	//freopen("input.txt", "r", stdin);freopen("output.txt", "w", stdout);
	//freopen(NAME".in", "r", stdin);freopen(NAME".out", "w", stdout);
	cin >> n;
	s = 1;
	while (s < n) {
		s <<= 1;
	}
	for (int i = 0; i < n; i++) {
		scanf("%d", &q[i]);
		a[0][s + i] = ((i & 1) ? inf : q[i]);
		a[1][s + i] = ((i & 1) ? q[i] : inf);
		rmq[0][s + i] = s + i;
		rmq[1][s + i] = s + i;
	}
	for (int i = s - 1; i > 0; i--) {
		rmq[0][i] = (a[0][rmq[0][i * 2]] > a[0][rmq[0][i * 2 + 1]] ? rmq[0][i * 2 + 1] : rmq[0][i * 2]);
		rmq[1][i] = (a[1][rmq[1][i * 2]] > a[1][rmq[1][i * 2 + 1]] ? rmq[1][i * 2 + 1] : rmq[1][i * 2]);
	}
	for (int i = 0; i < nmax; i++) {
		answer[i] = mp(-1, -1);
		par[i] = -1;
	}
	get(0, n - 1, 0);
	nowa.insert(node(answer[0].first, answer[0].second, 0));
	while (nowa.size()) {
		node now = *nowa.begin();
		printf("%d %d ", now.x, now.y);
		nowa.erase(nowa.begin());
		for (int u : go[now.z]) {
			if (answer[u].first != -1) {
				nowa.insert(node(answer[u].first, answer[u].second, u));
			}
		}
	}
	return 0;
}


Measured memory_bytes: 98432