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::collections::BinaryHeap;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
#[derive(Clone, Ord, Eq, PartialOrd, PartialEq)]
struct Node {
    a: i32,
    index: usize,
}

#[allow(dead_code)]
impl Node {
    fn new(a: i32, index: usize) -> Node {
        Node { a: a, index: index }
    }
    fn default_value() -> Node {
        Node {
            a: i32::max_value(),
            index: 0,
        }
    }
}
#[allow(dead_code)]
fn merge(left: &Node, right: &Node) -> Node {
    std::cmp::min(left.clone(), right.clone())
}

#[allow(dead_code)]
#[derive(Clone)]
struct SegmentTree {
    max_depth: usize,
    data: Vec<Node>,
}
#[allow(dead_code)]
impl SegmentTree {
    fn new(n: usize) -> SegmentTree {
        let mut max_depth = 0;
        while (1 << max_depth) < n {
            max_depth += 1;
        }
        SegmentTree {
            max_depth: max_depth,
            data: vec![Node::default_value(); 1 << (max_depth + 1)],
        }
    }
    fn set(&mut self, index: usize, value: Node) {
        let mut target = (1 << self.max_depth) + index;
        self.data[target] = value;
        for _ in 0..self.max_depth {
            target >>= 1;
            self.data[target] = merge(&self.data[target * 2], &self.data[target * 2 + 1]);
        }
    }
    // [left, right)
    fn get(&self, left: usize, right: usize) -> Node {
        assert!(left < right);
        self.in_get(0, 1, left, right)
    }
    fn in_get(&self, depth: usize, node: usize, left: usize, right: usize) -> Node {
        let width = 1 << (self.max_depth - depth);
        let index = node - (1 << depth);
        let node_left = index * width;
        let node_mid = node_left + (width >> 1);
        if right - left == width && left == node_left {
            return self.data[node].clone();
        } else if right <= node_mid {
            return self.in_get(depth + 1, node * 2, left, right);
        } else if node_mid <= left {
            return self.in_get(depth + 1, node * 2 + 1, left, right);
        }
        merge(
            &self.in_get(depth + 1, node * 2, left, node_mid),
            &self.in_get(depth + 1, node * 2 + 1, node_mid, right),
        )
    }
}

fn main() {
    let n = read::<usize>();
    let mut seq = vec![0; n];
    let mut stree = vec![SegmentTree::new(n); 2];
    for i in 0..n {
        seq[i] = read::<i32>() - 1;
        stree[i % 2].set(i, Node::new(seq[i], i));
    }
    let mut que = BinaryHeap::new();
    let mut ans = vec![];
    que.push((-stree[0].get(0, n).a, 0, n));
    while let Some((_, l, r)) = que.pop() {
        let left = stree[l % 2].get(l, r);
        let left_value = left.a;
        let left_index = left.index;
        let right = stree[(left_index + 1) % 2].get(left_index + 1, r);
        let right_value = right.a;
        let right_index = right.index;
        ans.push(left_value);
        ans.push(right_value);
        if l != left_index {
            que.push((-stree[l % 2].get(l, left_index).a, l, left_index));
        }
        if left_index + 1 != right_index {
            que.push((
                -stree[(left_index + 1) % 2]
                    .get(left_index + 1, right_index)
                    .a,
                left_index + 1,
                right_index,
            ));
        }
        if right_index + 1 != r {
            que.push((
                -stree[(right_index + 1) % 2].get(right_index + 1, r).a,
                right_index + 1,
                r,
            ));
        }
    }
    for i in 0..n {
        if i != 0 {
            print!(" ");
        }
        print!("{}", ans[i] + 1);
    }
    println!("");
}