#include <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cassert>
#include <utility>
#include <iomanip>
#include <chrono>
#include <random>
#include <bitset>

using namespace std;

#define sz(x) (int) x.size()
#define all(a) a.begin(), a.end()
#define y1 aksjdaskdjksjfksdjf
#define left kdnvldvoiwejifejg
#define right lkdsjflksdjfdjfk
#define prev asdasfsadjkjsdfjs
#define tm aklsjdasjdasjdkdjjf
#define lcm hddalkwjeidjjhasda
#define random_shuffle asdasdd

const int MAXN = 205000;

class SegmentTree {
private: 
  const long long INF = 1e18;
  vector<pair<long long, int>> tree;
  int n;
public:
  void init(int sz) {
    n = 1;
    while (n < sz) {
      n *= 2;
    }
    tree.assign(2 * n, {INF, -1});
  }

  // l, r are in [0, n - 1]
  pair<long long, int> getMin(int l, int r) {
    l = n + l; r = n + r;
    pair<long long, int> res = {INF, -1};
    
    while (l <= r) {
      if (l & 1) {
        res = min(res, tree[l]);
        l++;
      }
      if (r % 2 == 0) {
        res = min(res, tree[r]);
        r--;
      }
      l /= 2; r /= 2;
    }
    return res;
  }

  // pos is in [0, n - 1]
  void update(int pos, long long val) {
    pos = n + pos;
    tree[pos] = {val, pos - n};
    pos /= 2;
    while (pos >= 1) {
      tree[pos] = min(tree[pos * 2], tree[pos * 2 + 1]);
      pos /= 2;
    }
  }
};

struct Segment {
    int l, r;
    int mn1, mn2;
    int mn1Pos, mn2Pos;

    bool operator < (const Segment& o) const {
        return !(mn1 < o.mn1 || (mn1 == o.mn1 && mn2 < o.mn2));
    }
};

int n;
int p[MAXN];
vector<int> q;
priority_queue <Segment> pq;
SegmentTree treeOdd, treeEven;

void update(int l, int r) {
    if (l > r) {
        return;
    }
    if (l & 1) {
        pair <long long, int> mnOdd = treeOdd.getMin(l, r);
        if (mnOdd.second != -1) {
            pair <long long, int> mnEven = treeEven.getMin(mnOdd.second + 1, r);
            pq.push({l, r, (int) mnOdd.first, (int) mnEven.first, mnOdd.second, mnEven.second});
        }
    } else {
        pair <long long, int> mnEven = treeEven.getMin(l, r);
        if (mnEven.second != -1) {
            pair <long long, int> mnOdd = treeOdd.getMin(mnEven.second + 1, r);
            pq.push({l, r, (int) mnEven.first, (int) mnOdd.first, mnEven.second, mnOdd.second});
        }
    }
}

int main() {

    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &p[i]);
    }

    treeOdd.init(n);
    treeEven.init(n);
    for (int i = 0; i < n; i++) {
        if (i & 1) {
            treeOdd.update(i, p[i]);
        } else {
            treeEven.update(i, p[i]);
        }
    }

    update(0, n - 1);

    while (!pq.empty()) {
        Segment cur = pq.top();
        pq.pop();
        q.push_back(cur.mn1);
        q.push_back(cur.mn2);
        update(cur.l, cur.mn1Pos - 1);
        update(cur.mn1Pos + 1, cur.mn2Pos - 1);
        update(cur.mn2Pos + 1, cur.r);
    }

    for (int i = 0; i < n; i++) {
        printf("%d ", q[i]);
    }
    cout << endl;

    return 0;
}


Measured memory_bytes: 21428