#include <random>
#include "bits/stdc++.h"

using namespace std;

using P = pair<int, int>;

template <typename T>
void printv(const vector<T> &v) {
  int sz = v.size();
  for (int i = 0; i < sz; i++) {
    cout << v[i] << " \n"[i == sz - 1];
  }
}

// (val, pos)
struct RangeMinimumQuery {
  using type = P;
  static type id() { return P(INT_MAX, -1); }
  static type op(const type &l, const type &r) { return std::min(l, r); }
};

template <typename M>
class SegmentTree {
  using T = typename M::type;
  int n;
  std::vector<T> node;

 public:
  // Monoid::id 初期化
  SegmentTree(int _n) {
    n = 1;
    while (n < _n) n *= 2;
    node.resize(2 * n, M::id());
  }
  // x 番目を val に更新
  void update(int x, T val) {
    x += n;
    node[x] = val;
    while (x >>= 1) {
      node[x] = M::op(node[2 * x], node[2 * x + 1]);
    }
  }
  // v[x] を M::op(v[x], val) に更新
  void operation(int x, T val) {
    x += n;
    node[x] = M::op(node[x], val);
    while (x >>= 1) {
      node[x] = M::op(node[2 * x], node[2 * x + 1]);
    }
  }
  // [a, b) の op
  T query(int l, int r) {
    l += n;
    r += n;
    T retl = M::id(), retr = M::id();
    while (l < r) {
      if (l & 1) retl = M::op(retl, node[l++]);
      if (r & 1) retr = M::op(node[--r], retr);
      l >>= 1;
      r >>= 1;
    }
    return M::op(retl, retr);
  }
};

const int MAX_N = 200010;
SegmentTree<RangeMinimumQuery> seg_odd(MAX_N), seg_even(MAX_N), seg(MAX_N);
int n;
vector<int> ans;
vector<int> p(MAX_N);

//
struct Result {
  int mi, lpos, rpos;
};

// [l, r] の Result を求める
Result calc(int l, int r) {
  if (l % 2) {
    auto np = seg_odd.query(l, r);
    int lpos = np.second, mi = np.first;
    np = seg_even.query(lpos + 1, r + 1);
    return Result{mi, lpos, np.second};
  }
  auto np = seg_even.query(l, r);
  int lpos = np.second, mi = np.first;
  np = seg_odd.query(lpos + 1, r + 1);
  return Result{mi, lpos, np.second};
}

// 最小値, 左端/右端
struct State {
  int mi, l, r;
};

bool operator<(const State &lhs, const State &rhs) { return lhs.mi > rhs.mi; }

void solve() {
  priority_queue<State> que;
  que.push(State{0, 0, n - 1});
  while (!que.empty()) {
    auto s = que.top();
    que.pop();
    auto result = calc(s.l, s.r);
    ans.push_back(p[result.lpos]);
    ans.push_back(p[result.rpos]);
    //cerr << "l: " << s.l << " r:" << s.r << endl;
    if (s.l < result.lpos) {
      int nl = s.l, nr = result.lpos - 1;
      //cerr << "nl: " << nl << " nr:" << nr << endl;
      assert((nr - nl) % 2);
      auto r = calc(nl, nr);
      que.push(State{r.mi, nl, nr});
    }
    if (result.lpos + 1 < result.rpos) {
      int nl = result.lpos + 1, nr = result.rpos - 1;
      //cerr << "nl: " << nl << " nr:" << nr << endl;
      assert((nr - nl) % 2);
      auto r = calc(nl, nr);
      que.push(State{r.mi, nl, nr});
    }
    if (result.rpos < s.r) {
      int nl = result.rpos + 1, nr = s.r;
      //cerr << "nl: " << nl << " nr:" << nr << endl;
      assert((nr - nl) % 2);
      auto r = calc(nl, nr);
      que.push(State{r.mi, nl, nr});
    }
  }
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin >> n;
  for (int i = 0; i < n; i++) {
    cin >> p[i];
    seg.update(i, {p[i], i});
    if (i % 2) {
      seg_odd.update(i, {p[i], i});
    } else {
      seg_even.update(i, {p[i], i});
    }
  }
  solve();
  printv(ans);
}


Measured memory_bytes: 18096