#include <iostream>
#include <algorithm>
#include <time.h>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cassert>

using namespace std;

const int N = 200005;
const int inf = 1000 * 1000 * 1000;
const int mod = 1000 * 1000 * 1000 + 7;

int n , a[N] , ind[N];
int T[4 * N][3] , d[4 * N];
int t[4 * N];

void build(int v,int s,int e){
    if(s == e){
        if(s % 2){
            T[v][0] = a[s];
            T[v][1] = inf;
            t[v] = a[s];
        }
        else{
            T[v][0] = inf;
            T[v][1] = a[s];
            t[v] = a[s];
        }
        return ;
    }
    int m = (s + e) / 2;
    build(2*v , s , m);
    build(2*v+1 , m+1 , e);
    T[v][0] = min(T[2*v][0] , T[2*v+1][0]);
    T[v][1] = min(T[2*v][1] , T[2*v+1][1]);
    t[v] = max(t[2*v] , t[2*v+1]);
}

void push(int v,int s,int e){
    if(d[v] == 0)return ;
    swap(T[v][0] , T[v][1]);
    if(s != e){
        d[2*v] ^= d[v];
        d[2*v+1] ^= d[v];
    }
    d[v] = 0;
}

void update(int v,int s,int e,int l,int r){
    push(v , s , e);
    if(l > r)return ;
    if(s == l && e == r){
        d[v] ^= 1;
        push(v , s , e);
        return ;
    }
    int m = (s + e) / 2;
    update(2*v , s , m , l , min(r , m));
    update(2*v+1 , m+1 , e , max(m+1,l) , r);
    T[v][0] = min(T[2*v][0] , T[2*v+1][0]);
    T[v][1] = min(T[2*v][1] , T[2*v+1][1]);
    t[v] = max(t[2*v] , t[2*v+1]);
}

void update1(int v,int s,int e,int pos){
    push(v , s , e);
    if(s == e){
        T[v][0] = T[v][1] = inf;
        t[v] = inf;
        return ;
    }
    int m = (s + e) / 2;
    if(pos <= m){
        update1(2*v , s , m , pos);
        push(2*v+1 , m+1 , e);
    }
    else{
        update1(2*v+1 , m+1 , e , pos);
        push(2*v , s , m);
    }
    T[v][0] = min(T[2*v][0] , T[2*v+1][0]);
    T[v][1] = min(T[2*v][1] , T[2*v+1][1]);
    t[v] = max(t[2*v] , t[2*v+1]);
}

int get(int v,int s,int e,int l,int r,int ind){
    push(v , s , e);
    if(l > r)return inf;
    if(s == l && e == r)return T[v][ind];
    int m = (s + e) / 2;
    return min( get(2*v , s , m , l , min(r , m) , ind) , get(2*v+1 , m+1 , e , max(m+1,l) , r , ind) );
}

int getmx(int v,int s,int e,int l,int r){
    push(v , s , e);
    if(l > r)return 0;
    if(s == l && e == r)return t[v];
    int m = (s + e) / 2;
    return max( getmx(2*v , s , m , l , min(r , m)) , getmx(2*v+1 , m+1 , e , max(m+1,l) , r) );
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        ind[a[i]] = i;
    }
    build(1 , 1 , n);
    for(int i=1;i<=n/2;i++){
        int A = get(1 , 1 , n , 1 , n , 0);
        int ina = ind[A] + 1 , inb = n , id;
        while(ina <= inb){
            int mid = (ina + inb) / 2;
            int T = getmx(1 , 1 , n , ind[A] + 1 , mid);
            if(T != inf){
                id = mid;
                ina = mid + 1;
            }
            else
                inb = mid - 1;
        }
        int B = get(1 , 1 , n , ind[A] + 1 , id , 1);
        printf("%d %d ",A,B);
        update(1 , 1 , n , ind[A] + 1 , ind[B] - 1);
        update1(1 , 1 , n , ind[A]);
        update1(1 , 1 , n , ind[B]);
    }
    cout<<endl;
    return 0;
}



Measured memory_bytes: 18816