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 Rust (1.15.1) (judge verdict: Accepted)

use std::io;
use std::str::FromStr;
use std::cmp;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::io::{stdout, Write, BufWriter};

const INT_MAX: i64 = 200001;

struct SegmentTree {
    n: usize, 
    dat: Vec<i64>
}

impl SegmentTree {
    fn new(nn: usize) -> SegmentTree {
        let mut n = 1;
        while n < nn {
            n *= 2;
        }
        let dat = vec![INT_MAX; 2*n-1];
        return SegmentTree {n: n, dat: dat};
    }

    fn update(&mut self, k: usize, a: i64) {
        let mut i = k + (self.n - 1);
        self.dat[i] = a;
        while i > 0 {
            i = (i - 1) / 2;
            self.dat[i] = cmp::min(self.dat[i*2+1], self.dat[i*2+2]);
        }
    }
    fn query(&self, a: usize, b: usize, k: usize, l: usize, r: usize) -> i64 {
        if (r <= a) || (b <= l) {
            return INT_MAX;
        }
        if (a <= l) && (r <= b) {
            return self.dat[k];
        }
        let vl = self.query(a, b, k*2+1, l, (l+r)/2);
        let vr = self.query(a, b, k*2+2, (l+r)/2, r);
        return cmp::min(vl, vr);
    }
}

enum EvenOdd {
    E,
    O,
}

#[derive(Copy, Clone, Eq, PartialEq)]
struct Item {
    v: i64,
    i: usize,
    left: usize,
    right: usize,
}

// Priority Queue
impl Ord for Item {
    fn cmp(&self, other: &Item) -> Ordering {
        other.v.cmp(&self.v)
    }
}

impl PartialOrd for Item {
    fn partial_cmp(&self, other: &Item) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

fn join(v: Vec<i64>) -> String {
    let mut ret = String::new();
    let n = v.len();
    for (i, x) in v.iter().enumerate() {
        if i == n - 1 {
            ret.push_str(&format!("{}", x));
        } else {
            ret.push_str(&format!("{} ", x));
        }
    }
    return ret
}

fn gets() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).ok();
    return buf
}

fn split<T>(buf: String) -> Vec<T> 
  where T: std::str::FromStr,
  <T as std::str::FromStr>::Err: std::fmt::Debug {
    buf.split_whitespace()
        .map(|n| n.parse::<T>().unwrap())
        .collect()
}

fn main() {
    let n = usize::from_str(gets().trim()).unwrap();
    let arr: Vec<i64> = split(gets());

    let mut st_even = SegmentTree::new(n);
    let mut st_odd = SegmentTree::new(n);
    let mut h = HashMap::new();

    for (i, a) in arr.iter().enumerate() {
        h.insert(a, i);
        match i%2 {
            0 => st_even.update(i, a.clone()),
            _ => st_odd.update(i, a.clone()),
        }
    }

    let wrap_query = |t: EvenOdd, a: usize, b: usize, k: usize, l: usize| {
        match (t, a%2) {
            (EvenOdd::E, 0) => st_even.query(a, b, k, l, st_even.n),
            (EvenOdd::E, 1) => st_odd.query(a, b, k, l, st_odd.n),
            (EvenOdd::O, 0) => st_odd.query(a, b, k, l, st_odd.n),
            _ => st_even.query(a, b, k, l, st_even.n),
        }
    };

    let mut q = vec![0; n];
    let mut pq = BinaryHeap::<Item>::new();
    let x = wrap_query(EvenOdd::E, 0, n, 0, 0);
    pq.push(Item{v: x, i: h[&x], left: 0, right: n});
    let mut ii = 0;
    while pq.len() != 0 {
        let item = pq.pop().unwrap();
        q[ii] = item.v;
        ii = ii + 1;
        let q1 = wrap_query(EvenOdd::O, item.i, item.right, 0, 0);
        let j = h[&q1];
        q[ii] = q1;
        ii = ii + 1;

        if item.i - item.left > 1 {
            let x = wrap_query(EvenOdd::E, item.left, item.i, 0, 0);
            pq.push(Item{v: x, i: h[&x], left: item.left, right: item.i});
        }
        if j - (item.i + 1) > 1 {
            let x = wrap_query(EvenOdd::E, item.i+1, j, 0, 0);
            pq.push(Item{v: x, i: h[&x], left: item.i + 1, right: j});
        }
        if item.right - (j + 1) > 1 {
            let x = wrap_query(EvenOdd::E, j+1, item.right, 0, 0);
            pq.push(Item{v: x, i: h[&x], left: j + 1, right: item.right});
        }
    }
    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    writeln!(out, "{}", join(q)).unwrap();
}