#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define FORE(i,c) FOR(i,0,SIZE(c)-1)
#define FORDE(i,c) FORD(i,SIZE(c)-1,0)

#define pb push_back
#define mp make_pair
#define st first
#define nd second


using namespace std;

typedef long long ll;
typedef pair <int,int> pii;
typedef pair <ll,ll> pll;

typedef vector <int> VI;
typedef vector <bool> VB;
typedef vector <pii> VP;
typedef vector <ll> VL;
typedef vector <pll> VPL;

typedef vector <VI> VVI;
typedef vector <VL> VVL;
typedef vector <VB> VVB;
typedef vector <VP> VVP;

const int MOD = 1000000007;
const int INF = 1000000001;
const ll LINF = 1000000000000000001LL;


struct MinTree {
    typedef int val_t;
    const val_t INIT = 1 << 30;

    val_t combine(const val_t &a, const val_t &b) {
        return min(a,b);
    }

    vector <val_t> T;
    int p = 1;

    MinTree(int n) {
        while (p < n) p *= 2;
        T.resize(2*p-1, INIT);
    }

    int par(int x) { return (x - 1) / 2; }

    void set(int l, val_t v) {
        l += p-1;
        T[l] = v;

        while (l > 0) {
            l = par(l);
            T[l] = combine(T[2*l+1], T[2*l+2]);
        }
    }

    val_t query(int l, int r) {
        l += p-1; r += p-1;
        val_t ans = combine(T[l],T[r]);

        while (par(l) != par(r)) {
            if (l%2 == 1) ans = combine(ans,T[l+1]);
            if (r%2 == 0) ans = combine(ans,T[r-1]);

            l = par(l);
            r = par(r);
        }

        return ans;
    }
};

/*************************************************************************/

VP mergeParts(VVP &parts) {
    VP res;
    
    for (auto &part : parts) {
        VP newRes(res.size() + part.size());
        merge(res.begin(), res.end(), part.begin(), part.end(), newRes.begin());
        
        res = newRes;
    }
    
    return res;
}

struct vertex {
    int id;
    VI edges;
    
    pii value;
};

int solve(int l, int r, MinTree &treeOdd, MinTree &treeEven, VI &where, vector <vertex> &graph) {
    if (l > r) return -1;
    
    int x;
    if (l % 2) x = treeOdd.query(l, r-1);
    else x = treeEven.query(l, r-1);
    
    int y;
    if (l % 2) y = treeEven.query(where[x]+1, r);
    else y = treeOdd.query(where[x]+1, r);
    
    VI edges = {
        solve(l, where[x]-1, treeOdd, treeEven, where, graph),
        solve(where[x]+1, where[y]-1, treeOdd, treeEven, where, graph),
        solve(where[y]+1, r, treeOdd, treeEven, where, graph)
    };
    
    graph.pb({
        SIZE(graph),
        edges,
        {x, y}
    });
    
    return SIZE(graph)-1;
}

/*************************************************************************/

int main() {
    ios_base::sync_with_stdio(0);
    
    int n;
    cin >> n;
    
    VI p(n), where(n);
    FOR(i,0,n-1) {
        cin >> p[i]; p[i]--;
        where[p[i]] = i;
    }
    
    MinTree treeOdd(n), treeEven(n);
    
    FOR(i,0,n-1) {
        if (i % 2) {
            treeOdd.set(i, p[i]);
        } else {
            treeEven.set(i, p[i]);
        }
    }
    
    vector <vertex> graph;
    int root = solve(0, n-1, treeOdd, treeEven, where, graph);
     
    VP ans;
    
    set <pair<pii,int>> see;
    see.insert({graph[root].value, root});
    
    while (!see.empty()) {
        ans.pb(see.begin()->st);
        int id = see.begin()->nd;
        
        see.erase(see.begin());
        
        for (int u : graph[id].edges) if (u != -1) {
            see.insert({graph[u].value, u});
        }
    }
    
    for (auto &e : ans) {
        cout << 1 + e.st << ' ' << 1 + e.nd << ' ';
    }

    return 0;
}

/*************************************************************************/


Measured memory_bytes: 30860