#include <bits/stdc++.h>

using namespace std;

#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define dump(x) cerr << #x " = " << (x) << '\n'
#define sz(x) ((int)(x).size())
#define endl '\n'

#ifdef _DEBUG27_
    //#define STRESS 1
#endif

typedef long long llong;

const int INF = 2e9;
const llong LINF = 2e18;

void inv(bool e);
template<typename T> T sign(T a);
template<typename T> void die(T &a);
template<typename T> void umax(T &a, T b);
template<typename T> void umin(T &a, T b);

bool brute, alter;
int cnt_tests = 1;

// Improving atcoter rating

// Code below

int n, w, h;

vector<pair<int, int> > arr, enArr;

void inp() {
    cin >> n;
    arr.resize(n);
    int k = 0;
    for (auto &x: arr) {
        cin >> x.fi;
        x.se = k++;
        if (x.se % 2) {
            enArr.pb(x);
        }
    }
}

template<typename T>
struct segment_tree {
    vector<T> orig, data;
    vector<int> need;
    T net;
    T (*f)(T a, T b);
    segment_tree() {

    }
    void build(int l, int r, int v = 0) {
        if (l > r) {
            return;
        }
        if (l == r) {
            data[v] = orig[l];
            return;
        }
        int ls = v + v + 1, rs = v + v + 2, m = (l + r) >> 1;
        build(l, m, ls);
        build(m + 1, r, rs);
        data[v] = (*f)(data[ls], data[rs]);
    }
    T get(int l, int r, int ql, int qr, int v = 0) {
        push(l, r, v);
        if (l > qr || r < ql) {
            return net;
        }
        if (l == ql && qr == r) {
            return data[v];
        }
        int ls = v + v + 1, rs = v + v + 2, m = (l + r) >> 1;
        T resL = get(l, m, ql, min(m, qr), ls);
        T resR = get(m + 1, r, max(m + 1, ql), qr, rs);
        return (*f)(resL, resR);
    }
    T get(int ql, int qr) {
        return get(0, sz(orig) - 1, ql, qr);
    }
    void change(int l, int r, int pos, T val, int v = 0) {
        push(l, r, v);
        if (pos > r || pos < l) {
            return;
        }
        if (l == r && l == pos) {
            orig[l] = data[v] = val;
            return;
        }
        int ls = v + v + 1, rs = v + v + 2, m = (l + r) >> 1;
        change(l, m, pos, val, ls);
        change(m + 1, r, pos, val, rs);
        data[v] = (*f)(data[ls], data[rs]);
    }
    void change(int pos, T val) {
        change(0, sz(orig) - 1, pos, val);
    }
    void push(int l, int r, int v) {
        if (!need[v])
            return;
        swap(data[v].fi, data[v].se);
        need[v] = false;
        if (l != r) {
            need[v + v + 1] = !need[v + v + 1];
            need[v + v + 2] = !need[v + v + 2];
        }
    }
    void paint(int l, int r, int ql, int qr, int v = 0) {
        push(l, r, v);
        if (l > qr || r < ql) {
            return;
        }
        if (l == ql && qr == r) {
            need[v] = !need[v];
            push(l, r, v);
            return;
        }
        int ls = v + v + 1, rs = v + v + 2, m = (l + r) >> 1;
        paint(l, m, ql, min(m, qr), ls);
        paint(m + 1, r, max(m + 1, ql), qr, rs);
        data[v] = (*f)(data[ls], data[rs]);
    }
    void paint(int ql, int qr) {
        paint(0, sz(orig) - 1, ql, qr);
    }
    void build(vector<T> &prot, T nt, T (*ff)(T a, T b)) {
        f = ff;
        net = nt;
        orig = prot;
        data.resize(4 * sz(prot) + 1, nt);
        need.resize(sz(data), 0);
        build(0, sz(prot) - 1);
    }
};

typedef pair<pair<int, int>, pair<int, int> > pt;

pt F(pt a, pt b) {
    return pt(min(a.fi, b.fi), min(a.se, b.se));
}

const int N = 2e5 + 25;

int ans[N];

void solve() {
    segment_tree<pt> tree;
    pt nt = {{INF, INF}, {INF, INF}};
    vector<pt> base(n, nt);
    for (int i = 0; i < n; i++) {
        if (i % 2 == 0) {
            base[i].fi = arr[i];
        } else {
            base[i].se = arr[i];
        }
    }
    tree.build(base, nt, F);
    set<int> baned = {n};
    for (int i = 0; i < n / 2; i++) {
        pt cur = tree.get(0, n - 1);
        pair<int, int> ft = cur.fi;
        int l = ft.se + 1, r = *baned.upper_bound(ft.se) - 1;
        pt pr = tree.get(l, r);
        pair<int, int> sc = pr.se;
        ans[i + i] = ft.fi;
        ans[i + i + 1] = sc.fi;
        //cout << "! " << l << ' ' << r << endl;
        //cout << ft.fi << ' ' << sc.fi << endl;
        tree.change(ft.se, nt);
        tree.change(sc.se, nt);
        tree.paint(ft.se, sc.se);
        baned.insert(ft.se);
        baned.insert(sc.se);
        //cout << endl;
    }
    for (int i = 0; i < n; i++) {
        cout << ans[i] << ' ';
    }
}

void stress() {

}

void naive() {

}

void run();
int main() {
    #ifdef _DEBUG27_
        if (1)
            freopen("input.txt", "r", stdin);
    #else
        ios_base::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        if (0) {
            freopen("palindrome.in", "r", stdin);
            freopen("palindrome.out", "w", stdout);
        }
    #endif
    srand(time(0));
    #ifdef STRESS
        brute = true;
    #else
        brute = false;
    #endif

    for (int i = 0; (i < cnt_tests); i++) {
        run();
    }
    cerr << endl << "Time: " << clock() / 1000.0 << " ms";
    return 0;
}

void run() {
    if (!brute) {
        inp();
    }
    else {
        stress();
    }
    solve();
    cout << endl;
}

template<typename T>
void die(T &a) {
    cout << a;
    exit(0);
}

template<typename T>
T sign(T a) {
    if (a == 0)
        return 0;
    if (a < 0)
        return -1;
    return 1;
}

template<typename T>
void umax(T &a, T b) {
    if (b > a)
        a = b;
}

template<typename T>
void umin(T &a, T b) {
    if (b < a)
        a = b;
}

void inv(bool e) {
    if (!e) {
        vector<int> a;
        a[-1] += 1;
    }
}

/** CLEARING BUFFER

    cout << VAL << flush;

    OR

    printf(VAL);
    fflush(stdout);
*/


Measured memory_bytes: 35956