Problem:
Score : 800 points

Problem Statement

Let N be a positive even number.

We have a permutation of (1, 2, ..., N), p = (p_1, p_2, ..., p_N).
Snuke is constructing another permutation of (1, 2, ..., N), q, following the procedure below.

First, let q be an empty sequence.
Then, perform the following operation until p becomes empty:

Select two adjacent elements in p, and call them x and y in order. Remove x and y from p (reducing the length of p by 2), and insert x and y, preserving the original order, at the beginning of q.

When p becomes empty, q will be a permutation of (1, 2, ..., N).

Find the lexicographically smallest permutation that can be obtained as q.

Constraints

N is an even number.

2 ≤ N ≤ 2 × 10^5

p is a permutation of (1, 2, ..., N).

Input

Input is given from Standard Input in the following format:

N
p_1 p_2 ... p_N

Output

Print the lexicographically smallest permutation, with spaces in between.

Sample Input 1

4
3 2 4 1

Sample Output 1

3 1 2 4

The solution above is obtained as follows:

p

q

(3, 2, 4, 1)

()

↓

↓

(3, 1)

(2, 4)

↓

↓

()

(3, 1, 2, 4)

Sample Input 2

2
1 2

Sample Output 2

1 2

Sample Input 3

8
4 6 3 2 8 5 7 1

Sample Output 3

3 1 2 7 4 6 8 5

The solution above is obtained as follows:

p

q

(4, 6, 3, 2, 8, 5, 7, 1)

()

↓

↓

(4, 6, 3, 2, 7, 1)

(8, 5)

↓

↓

(3, 2, 7, 1)

(4, 6, 8, 5)

↓

↓

(3, 1)

(2, 7, 4, 6, 8, 5)

↓

↓

()

(3, 1, 2, 7, 4, 6, 8, 5)

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <cmath>
#include <queue>

#define REP(i,a,b) for(int i=int(a);i<int(b);i++)

using namespace std;

typedef long long int lli;

const int inf = 1 << 30;

class SqrtDiv {
private:
    vector<int> v;
    vector<int> block;
    int blockSize;
public:
    SqrtDiv(int n) {
        v.resize(n, inf);
        blockSize = ceil(sqrt(n) + 1e-9);
        block.resize((n + blockSize - 1) / blockSize, inf);
    }

    void set(int n, int x) {
        v[x] = n;
        x /= blockSize;
        block[x] = inf;
        REP (i, x * blockSize, (x + 1) * blockSize) {
            block[x] = min(block[x], v[i]);
        }
    }

    int get(int l, int r) {
        int ans = inf;
        REP (i, 0, block.size()) {
            int ll = i * blockSize;
            int rr = (i + 1) * blockSize;
            if (rr <= l || r <= ll) continue;
            else if (l <= ll && rr <= r) ans = min(ans, block[i]);
            else {
                REP (j, max(ll, l), min(rr, r)) {
                    ans = min(ans, v[j]);
                }
            }
        }
        return ans;
    }
};

struct Data {
    int l, r, m;
    Data(int l, int r, int m) : l(l), r(r), m(m) {}
};

bool operator<(const Data &d1, const Data &d2) {
    return d1.m > d2.m;
}

int main () {
    int N;
    cin >> N;
    map<int, int> ml;
    SqrtDiv sq[2] = {SqrtDiv(N), SqrtDiv(N)};
    REP (i, 0, N) {
        int ai;
        cin >> ai;
        ml[ai] = i;
        sq[0].set(ai, i);
        sq[1].set(ai, i);
        sq[!(i % 2)].set(inf, i);
    }

    priority_queue<Data, vector<Data>> pq;
    pq.emplace(0, N, sq[0].get(0, N));
    while (pq.size()) {
        auto t = pq.top();
        pq.pop();
        int lt = ml[t.m];
        int g = sq[!(t.r % 2)].get(lt + 1, t.r);
        int gpos = ml[g];
        if (t.l < lt) pq.emplace(t.l, lt, sq[t.l % 2].get(t.l, lt));
        if (lt + 1 < gpos) pq.emplace(lt + 1, gpos, sq[!(lt % 2)].get(lt + 1, gpos));
        if (gpos + 1 < t.r) pq.emplace(gpos + 1, t.r, sq[!(gpos % 2)].get(gpos + 1, t.r));
        cout << t.m << ' ' << g << ' ';
    }
    cout << endl;
    return 0;
}