fn get_line() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().to_string()
}

fn reads<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        <T as std::str::FromStr>::Err: std::fmt::Debug {
    get_line().split(' ').map(|x| x.parse().unwrap()).collect()
}

fn readln<T>() -> T
    where
        T: std::str::FromStr,
        <T as std::str::FromStr>::Err: std::fmt::Debug {
    get_line().parse().unwrap()
}

use std::collections::BinaryHeap;
use std::cmp::Ordering;

#[derive(Clone, Copy, Eq, PartialEq)]
struct E {
    num: usize,
    idx: usize,
}

impl Ord for E {
    fn cmp(&self, other: &Self) -> Ordering {
        other.num.cmp(&self.num)
    }
}

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

#[derive(Clone, Copy, Eq, PartialEq)]
struct R {
    num: E,
    lb: usize,
    rb: usize,
}

impl Ord for R {
    fn cmp(&self, other: &Self) -> Ordering {
        other.num.num.cmp(&self.num.num)
    }
}

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

struct SegTree<T> {
    elems: Vec<Option<T>>,
    num: usize,
}

impl<T: Clone + Copy + Ord> SegTree<T> {
    fn new(xs: &Vec<T>) -> Self {
        let l = xs.len();
        let n = (l as f64).log2().ceil().exp2() as usize;

        let mut res = SegTree {
            elems: vec![None; 2 * n - 1],
            num: n,
        };

        for (i, &x) in xs.iter().enumerate() {
            res.update(x, i);
        }

        res
    }

    fn update(&mut self, v: T, idx: usize) {
        let mut i = self.num + idx - 1;

        self.elems[i] = Some(v);

        while i > 0 {
            i = (i - 1) / 2;

            self.elems[i] =
            if let (Some(lhs), Some(rhs)) = (self.elems[i * 2 + 1], self.elems[i * 2 + 2]) {
                Some(std::cmp::max(lhs, rhs))
            }
            else {
                self.elems[i * 2 + 1]
            };
        }
    }

    fn query(&self, lb: usize, rb: usize) -> Option<T> {
        self.qf(lb, rb, 0, 0, self.num)
    }

    fn qf(&self, lb: usize, rb: usize, i: usize, clb: usize, crb: usize) -> Option<T> {
        if lb >= crb || clb >= rb {
            None
        }
        else if clb >= lb && rb >= crb {
            self.elems[i]
        }
        else {
            let mid = (clb + crb) / 2;

            let lv = self.qf(lb, rb, i * 2 + 1, clb, mid);
            let rv = self.qf(lb, rb, i * 2 + 2, mid, crb);

            match (lv, rv) {
                (Some(lhs), Some(rhs)) => {
                    Some(std::cmp::max(lhs, rhs))
                },
                (Some(lhs), _) => {
                    Some(lhs)
                },
                (_, Some(rhs)) => {
                    Some(rhs)
                },
                _ => {
                    None
                }
            }
        }
    }
}

fn main() {
    let n = readln();
    let ps = reads();

    let mut es = vec![];
    let mut os = vec![];

    for i in 0..n {
        let e = E {num: ps[i], idx: i};
        let d = E {num: n + 1, idx: i};
        if i % 2 == 0 {
            es.push(e);
            os.push(d);
        }
        else {
            es.push(d);
            os.push(e);
        }
    }

    let est = SegTree::new(&es);
    let ost = SegTree::new(&os);

    let mut q = BinaryHeap::new();
    q.push(
        R {
            num: est.query(0, n).unwrap(),
            lb: 0,
            rb: n,
        }
    );

    let mut qs = vec![];

    while let Some(r) = q.pop() {

        if r.rb - r.lb == 2 {
            qs.push(r.num.num);
            qs.push(ps[r.num.idx + 1]);
            continue;
        }

        let next =
        if r.num.idx % 2 == 0 {
            ost.query(r.num.idx + 1, r.rb).unwrap()
        }
        else {
            est.query(r.num.idx + 1, r.rb).unwrap()
        };

        qs.push(r.num.num);
        qs.push(next.num);

        if r.num.idx > r.lb {
            q.push(
                R {
                    num:
                    if r.lb % 2 == 0 {
                        est.query(r.lb, r.num.idx).unwrap()
                    }
                    else {
                        ost.query(r.lb, r.num.idx).unwrap()
                    },
                    lb: r.lb,
                    rb: r.num.idx
                }
            );
        }
        if next.idx > r.num.idx + 1 {
            q.push(
                R {
                    num:
                    if r.num.idx % 2 == 1 {
                        est.query(r.num.idx + 1, next.idx).unwrap()
                    }
                    else {
                        ost.query(r.num.idx + 1, next.idx).unwrap()
                    },
                    lb: r.num.idx + 1,
                    rb: next.idx
                }
            );
        }
        if r.rb > next.idx + 1 {
            q.push(
                R {
                    num:
                    if next.idx % 2 == 1 {
                        est.query(next.idx + 1, r.rb).unwrap()
                    }
                    else {
                        ost.query(next.idx + 1, r.rb).unwrap()
                    },
                    lb: next.idx + 1,
                    rb: r.rb
                }
            );
        }
    }

    for i in 0..(n - 1) {
        print!("{} ", qs[i]);
    }
    println!("{}", qs[n - 1]);
}


Measured memory_bytes: 45908