#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>


#define INF 1000000000
#define MOD 1000000007
#define ALL(x) std::begin(x), std::end(x)


template<class T>
class segment_tree_t {
public:
  segment_tree_t(int size) : size_(1), xp_(std::numeric_limits<T>::max()) {
    while (size_ < size)
      size_ *= 2;

    a_ = new T[size_ * 2];

    for (int i = 0, size = size_ * 2; i < size; i ++)
      a_[i] = xp_;
  };

  ~segment_tree_t() {
    delete[] a_;
  };

public:
  void update(int i, T x) {	// 0-index
    i += size_ - 1;

    a_[i] = x;

    while (i > 0) {
      i = (i - 1) / 2;

      a_[i] = std::min(a_[i * 2 + 1], a_[i * 2 + 2]);
    }
  };

  T query(int a, int b, int k = -1, int l = -1, int r = -1) {	// [a, b)
    if (k < 0) {
      return query(a, b, 0, 0, size_);
    }
    else {
      if (r <= a || b <= l)
        return xp_;

      if (a <= l && r <= b) {
        return a_[k];
      }
      else {
        return std::min(query(a, b, k * 2 + 1, l, (l + r) / 2),
                        query(a, b, k * 2 + 2, (l + r) / 2, r));
      }
    }
  };

private:
  int size_;

  T* a_;

  T xp_;
};


class range_t {
public:
  range_t(int ll = -1, int rr = -1, int xx = -1) : l(ll), r(rr), x(xx) {};

public:
  bool operator<(const range_t& a) const {
    return x > a.x;
  };
    
public:
  int l;
  int r;
  int x;
};


int N, p[222222], index_[222222];


int main(int argc, char** argv)
{
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(0);

  std::cout << std::fixed << std::setprecision(6);

  std::cin >> N;

  int* index = index_;

  segment_tree_t<int> etree(N / 2), otree(N / 2);

  for (int i = 0; i < N; i ++) {
    std::cin >> p[i];

    index[p[i]] = i;

    if (i % 2 == 0) {
      etree.update(i / 2, p[i]);
    }
    else {
      otree.update(i / 2, p[i]);
    }
  }

  std::priority_queue<range_t> pq;

  pq.emplace(0, N, etree.query(0, N / 2));

  std::vector<int> a;

  while (! pq.empty()) {
    range_t range = pq.top(); pq.pop();
    
    int l = range.l, r = range.r, x = range.x, y = -1, ll, rr;

    if (l % 2 == 0) {
      y = otree.query(index[x] / 2, (r + 1) / 2);

      assert(etree.query(index[x] / 2, index[x] / 2 + 1) == x);
      assert(otree.query(index[y] / 2, index[y] / 2 + 1) == y);

      etree.update(index[x] / 2, INF);
      otree.update(index[y] / 2, INF);
    }
    else {
      y = etree.query((index[x] + 1) / 2, (r + 1) / 2);

      assert(otree.query(index[x] / 2, index[x] / 2 + 1) == x);
      assert(etree.query(index[y] / 2, index[y] / 2 + 1) == y);

      otree.update(index[x] / 2, INF);
      etree.update(index[y] / 2, INF);
    }

    a.push_back(x);
    a.push_back(y);

    std::vector<std::pair<int, int>> pairs = { { l,            index[x] },
                                               { index[x] + 1, index[y] },
                                               { index[y] + 1, r        }
    };

    for (const auto& pair : pairs)
      if (pair.second - pair.first > 0) {
        if (pair.first % 2 == 0) {
          pq.emplace(pair.first, pair.second, etree.query(pair.first / 2, pair.second / 2));
        }
        else {
          pq.emplace(pair.first, pair.second, otree.query(pair.first / 2, pair.second / 2));
        }
      }
  }

  for (const auto& i : a)
    std::cout << i << ' ';
  std::cout << std::endl;

  return 0;
}


Measured memory_bytes: 6580