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::io::{Read, Stdin};
use std::str;
use std::str::FromStr;
use std::usize;
use std::cmp;
use std::fmt::Debug;
use std::i64::MAX;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct Candidate {
    minimum: i64,
    from: usize,
    until: usize,
}

impl Ord for Candidate {
    fn cmp(&self, other: &Candidate) -> Ordering {
        other.minimum.cmp(&self.minimum)
    }
}

// `PartialOrd` needs to be implemented as well.
impl PartialOrd for Candidate {
    fn partial_cmp(&self, other: &Candidate) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

fn go(from: usize, until: usize, even_rmq: &RangeMinimumQuery, odd_rmq: &RangeMinimumQuery, rev: &Vec<usize>, ans: &mut Vec<i64>, arr: &Vec<i64>) {
    let mut heap = BinaryHeap::new();
    heap.push(Candidate { minimum: 0, from: from, until: until });
    while !heap.is_empty() {
        let s: Candidate = heap.pop().unwrap();
        let from = s.from;
        let until = s.until;

        let (head, tail) = if from % 2 == 0 {
            let minimum_value = even_rmq.query(from, until);
            let minimum_index = rev[minimum_value as usize];
            let pair = odd_rmq.query(minimum_index + 1, until);
            let pair_index = rev[pair as usize];
            (minimum_index, pair_index)
        } else {
            let minimum_value = odd_rmq.query(from, until);
            let minimum_index = rev[minimum_value as usize];
            let pair = even_rmq.query(minimum_index + 1, until);
            let pair_index = rev[pair as usize];
            (minimum_index, pair_index)
        };
        ans.push(arr[head]);
        ans.push(arr[tail]);

        for &(left, right) in &[(from, head), (head + 1, tail), (tail + 1, until)] {
            if left >= right { continue; }
            let minimum = if left % 2 == 0 { even_rmq.query(left, right) } else { odd_rmq.query(left, right) };
            heap.push(Candidate { minimum: minimum, from: left, until: right });
        }
    }
}

fn main() {
    let mut sc = Scanner::new();
    let n = sc.parse::<usize>();
    let arr = (0..n).map(|_| {
        sc.parse::<i64>() - 1
    }).collect::<Vec<_>>();
    let mut rev = vec![0; n];
    for i in 0..n {
        rev[arr[i] as usize] = i;
    }

    let mut even_rmq = RangeMinimumQuery::new(n);
    let mut odd_rmq = RangeMinimumQuery::new(n);
    for i in 0..n {
        if i % 2 == 0 {
            even_rmq.update(i, arr[i]);
        } else {
            odd_rmq.update(i, arr[i]);
        }
    }

    let mut ans = Vec::new();
    go(0, n, &even_rmq, &odd_rmq, &rev, &mut ans, &arr);
    for t in &ans {
        print!("{} ", t + 1);
    }
    println!();
}

pub struct RangeMinimumQuery {
    seg: Vec<i64>,
    n: usize,
}

impl RangeMinimumQuery {
    pub fn new(size: usize) -> RangeMinimumQuery {
        let mut m = 1;
        while m <= size {
            m *= 2;
        }
        RangeMinimumQuery {
            seg: vec![MAX; m * 2],
            n: m,
        }
    }

    pub fn update(&mut self, mut k: usize, value: i64) {
        k += self.n - 1;
        self.seg[k] = value;
        while k > 0 {
            k = (k - 1) / 2;
            self.seg[k] = cmp::min(self.seg[k * 2 + 1], self.seg[k * 2 + 2]);
        }
    }

    /// Get the minimum value in the array in the range [a, b)
    ///
    /// # Panics
    ///
    /// Panics if `a >= b`.
    pub fn query(&self, a: usize, b: usize) -> i64 {
        assert!(a < b);
        return self.query_range(a, b, 0, 0, self.n);
    }

    pub fn query_range(&self, a: usize, b: usize, k: usize, l: usize, r: usize) -> i64 {
        if r <= a || b <= l {
            return MAX;
        }
        if a <= l && r <= b {
            return self.seg[k];
        }
        let x = self.query_range(a, b, k * 2 + 1, l, (l + r) / 2);
        let y = self.query_range(a, b, k * 2 + 2, (l + r) / 2, r);
        cmp::min(x, y)
    }
}

struct Scanner {
    stdin: Stdin,
    buf: Vec<u8>,
}

impl Scanner {
    fn new() -> Scanner {
        Scanner {
            stdin: io::stdin(),
            buf: Vec::with_capacity(256),
        }
    }

    fn parse<T: FromStr>(&mut self) -> T
        where <T as FromStr>::Err: Debug
    {
        self.buf.clear();
        let mut it = self.stdin.lock().bytes();
        let mut c = it.next().unwrap().unwrap();
        while c == ' ' as u8 || c == '\n' as u8 {
            c = it.next().unwrap().unwrap();
        }
        while !(c == ' ' as u8 || c == '\n' as u8) {
            self.buf.push(c);
            c = it.next().unwrap().unwrap();
        }
        str::from_utf8(&self.buf).unwrap().parse::<T>().unwrap()
    }
}