#include <bits/stdc++.h>
#define int long long
#define lint long long
#define pii pair<int,int>
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(c) (c).begin(),(c).end()
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define MINF(a) memset(a,0x3f,sizeof(a))
#define POW(n) (1LL<<(n))
#define IN(i,a,b) (a <= i && i <= b)
using namespace std;
template <typename T> inline bool CHMIN(T& a,T b) { if(a>b) { a=b; return 1; } return 0; }
template <typename T> inline bool CHMAX(T& a,T b) { if(a<b) { a=b; return 1; } return 0; }
template <typename T> inline void SORT(T& a) { sort(ALL(a)); }
template <typename T> inline void REV(T& a) { reverse(ALL(a)); }
template <typename T> inline void UNI(T& a) { sort(ALL(a)); a.erase(unique(ALL(a)),a.end()); }
template <typename T> inline T LB(vector<T>& v, T a) { return *lower_bound(ALL(v),a); }
template <typename T> inline int LBP(vector<T>& v, T a) { return lower_bound(ALL(v),a) - v.begin(); }
template <typename T> inline T UB(vector<T>& v, T a) { return *upper_bound(ALL(v),a); }
template <typename T> inline int UBP(vector<T>& v, T a) { return upper_bound(ALL(v),a) - v.begin(); }
template <typename T1, typename T2> ostream& operator<< (ostream& os, const pair<T1,T2>& p) { os << p.first << " " << p.second; return os; }
template <typename T1, typename T2> istream& operator>> (istream& is, pair<T1,T2>& p) { is >> p.first >> p.second; return is; }
template <typename T> ostream& operator<< (ostream& os, const vector<T>& v) { REP(i,v.size()) { if (i) os << " "; os << v[i]; } return os; }
template <typename T> istream& operator>> (istream& is, vector<T>& v) { for(T& in : v) is >> in; return is; }
template <typename T = int> vector<T> make_v(size_t a) { return vector<T>(a); }
template <typename T, typename... Ts> auto make_v(size_t a, Ts... ts) { return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...)); }
template <typename T, typename V> typename enable_if<is_class<T>::value == 0>::type fill_v(T &t, const V &v) { t = v; }
template <typename T, typename V> typename enable_if<is_class<T>::value != 0>::type fill_v(T &t, const V &v) { for(auto &e : t) fill_v(e,v); }
const lint MOD = 1000000007;
const lint INF = 0x3f3f3f3f3f3f3f3f;
const double EPS = 1e-10;

struct SegmentTree {
    using P = pair<int, int>;
    const int M1;
    int n;
    vector<P> d;

    SegmentTree(int M1) : M1(M1) {}

    P& f(P& lhs, P& rhs) {
        if (lhs.first == rhs.first)
            return lhs;
        return lhs.first < rhs.first ? lhs : rhs;
    }

    void init(int n_)
    {
        for (n = 1; n < n_; n <<= 1);
        d.assign(n << 1, P(M1, n));
        for (int i = n; i < n << 1; i++) {
            d[i] = P(M1, i - n);
        }
    }

    void build(const vector<int>& v)
	{
		int n_ = v.size();
		init(n_);
		for (int i = 0; i < n_; i++) {
			d[n + i] = P(v[i], i);
		}
		for (int i = n - 1; i > 0; i--) {
			d[i] = f(d[(i << 1) | 0], d[(i << 1) | 1]);
		}
	}

    void update(int k, int x)
	{
		d[k += n] = P(x, k);
		while (k >>= 1) {
			d[k] = f(d[(k << 1) | 0], d[(k << 1) | 1]);
		}
	}

	P query(int a, int b)
	{
		P L = P(M1, n);
        P R = P(M1, n);
		int l = a + n, r = b + n;
		while (l < r) {
			if (l & 1) L = f(L, d[l++]);
			if (r & 1) R = f(d[--r], R);
			l >>= 1, r >>= 1;
		}
		return f(L, R);
	}
};
using ST = SegmentTree;

signed main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

    int N;
    cin >> N;
    vector<int> p(N);
    cin >> p;
    vector<ST> st(2, ST(INF));
    REP(i, 2) {
        st[i].init(N);
    }
    REP(i, N) {
        st[i % 2].update(i, p[i]);
    }
    using P = tuple<pii, int, int>;
    priority_queue<P, vector<P>, greater<P>> q;
    q.emplace(st[0].query(0, N), 0, N);
    vector<int> ans;
    while (!q.empty()) {
        pii fir, sec;
        int l, r;
        tie(fir, l, r) = q.top(); q.pop();
        sec = st[(l % 2) ^ 1].query(fir.second + 1, r);
        ans.push_back(fir.first);
        ans.push_back(sec.first);
        if (l < fir.second)
            q.emplace(st[l % 2].query(l, fir.second), l, fir.second);
        if (fir.second + 1 < sec.second)
            q.emplace(st[(l % 2) ^ 1].query(fir.second + 1, sec.second), fir.second + 1, sec.second);
        if (sec.second + 1 < r)
            q.emplace(st[l % 2].query(sec.second + 1, r), sec.second + 1, r);        
    }
    cout << ans << endl;

    return 0;
}

Measured memory_bytes: 22512