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 Go (1.6) (judge verdict: Accepted)

package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"strconv"
)

func getScanner(fp *os.File) *bufio.Scanner {
	scanner := bufio.NewScanner(fp)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 500001), 500000)
	return scanner
}

func getNextString(scanner *bufio.Scanner) string {
	scanner.Scan()
	return scanner.Text()
}

func getNextInt(scanner *bufio.Scanner) int {
	i, _ := strconv.Atoi(getNextString(scanner))
	return i
}

func getNextInt64(scanner *bufio.Scanner) int64 {
	i, _ := strconv.ParseInt(getNextString(scanner), 10, 64)
	return i
}

func main() {
	fp := os.Stdin
	if len(os.Args) > 1 {
		fp, _ = os.Open(os.Args[1])
	}

	scanner := getScanner(fp)
	writer := bufio.NewWriter(os.Stdout)

	n := getNextInt(scanner)
	p := make(P, n)
	for i := 0; i < n; i++ {
		p[i] = getNextInt(scanner)
	}

	even := p.getSegTree(0)
	odd := p.getSegTree(1)

	rr := make(Ranges, 0)
	heap.Init(&rr)
	heap.Push(&rr, &Range{
		l:    0,
		r:    n,
		node: even.find(0, n/2, 0, 0, len(even)/2+1),
	})

	ans := make([]int, n)

	i := 0
	var node *Node
	for rr.Len() > 0 {
		r := heap.Pop(&rr).(*Range)
		if r.l == r.r {
			continue
		}
		ans[i] = r.node.v
		i++
		if r.node.i%2 == 0 {
			node = odd.find(r.node.i/2, r.r/2, 0, 0, len(odd)/2+1)
		} else {
			node = even.find((r.node.i+1)/2, (r.r+1)/2, 0, 0, len(even)/2+1)
		}
		ans[i] = node.v
		i++
		if r.r-r.l < 2 {
			continue
		}
		if r.l%2 == 0 {
			heap.Push(&rr, &Range{
				l:    r.l,
				r:    r.node.i,
				node: even.find(r.l/2, (r.node.i+1)/2, 0, 0, len(even)/2+1),
			})
			heap.Push(&rr, &Range{
				l:    r.node.i + 1,
				r:    node.i,
				node: odd.find(r.node.i/2, node.i/2, 0, 0, len(odd)/2+1),
			})
			heap.Push(&rr, &Range{
				l:    node.i + 1,
				r:    r.r,
				node: even.find((node.i+1)/2, (r.r+1)/2, 0, 0, len(even)/2+1),
			})
			continue
		}
		heap.Push(&rr, &Range{
			l:    r.l,
			r:    r.node.i,
			node: odd.find((r.l-1)/2, r.node.i/2, 0, 0, len(odd)/2+1),
		})
		heap.Push(&rr, &Range{
			l:    r.node.i + 1,
			r:    node.i,
			node: even.find((r.node.i+1)/2, (node.i+1)/2, 0, 0, len(even)/2+1),
		})
		heap.Push(&rr, &Range{
			l:    node.i + 1,
			r:    r.r,
			node: odd.find(node.i/2, r.r/2, 0, 0, len(odd)/2+1),
		})
	}

	for i := 0; i < n; i++ {
		fmt.Fprint(writer, ans[i])
		if i < n-1 {
			fmt.Fprint(writer, " ")
			continue
		}
		fmt.Fprintln(writer, "")
	}
	// m1 := even.find(0, 4, 0, 0, len(even)/2+1)
	// m2 := odd.find(0, 4, 0, 0, len(odd)/2+1)

	// fmt.Fprintln(writer, m1.i)
	// fmt.Fprintln(writer, m1.v)
	// fmt.Fprintln(writer, m2.i)
	// fmt.Fprintln(writer, m2.v)

	writer.Flush()
}

// Node ...
type Node struct {
	i, v int
}

// Nodes ...
type Nodes []*Node

func (nodes Nodes) find(l, r, k, s, t int) *Node {
	if l <= s && t <= r {
		return nodes[k]
	}
	if t <= l || r <= s {
		return &Node{
			i: -1,
			v: 1 << 30,
		}
	}
	left := nodes.find(l, r, 2*k+1, s, (s+t)/2)
	right := nodes.find(l, r, 2*k+2, (s+t)/2, t)
	if left.v < right.v {
		return left
	}
	return right
}

// P ...
type P []int

func (p P) find(l, r int) int {
	min := p[l]
	ans := l
	for i := l; i < r; i += 2 {
		if p[i] < min {
			min = p[i]
			ans = l
		}
	}
	return ans
}

func (p P) getSegTree(start int) Nodes {
	size := 1
	h := 1
	n := len(p)
	max := n >> 1
	if start == 1 {
		max = n - max
	}
	for size < max {
		size *= 2
		h++
	}
	seg := make(Nodes, 2<<uint(h)-1)
	for i := 0; i < 2<<uint(h)-1; i++ {
		seg[i] = &Node{
			i: -1,
			v: 1 << 30,
		}
	}
	leaf := 2<<uint(h-1) - 1
	for i := start; i < n; i += 2 {
		seg[leaf] = &Node{
			i: i,
			v: p[i],
		}
		for ii := leaf; ii > 0; ii = (ii - 1) >> 1 {
			if seg[(ii-1)>>1].v > p[i] {
				seg[(ii-1)>>1].v = p[i]
				seg[(ii-1)>>1].i = i
			}
		}
		leaf++
	}

	return seg
}

// Range ...
type Range struct {
	node *Node
	l, r int
}

// Ranges ...
type Ranges []*Range

func (a Ranges) Len() int           { return len(a) }
func (a Ranges) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a Ranges) Less(i, j int) bool { return a[i].node.v < a[j].node.v }

// Push ...
func (a *Ranges) Push(x interface{}) {
	*a = append(*a, x.(*Range))
}

// Pop ...
func (a *Ranges) Pop() interface{} {
	old := *a
	n := len(old)
	x := old[n-1]
	*a = old[0 : n-1]
	return x
}