// Slower C++ solution:
#include <bits/stdc++.h>



#define fr first

#define sc second

#define mk make_pair



using namespace std;



inline pair<int, int> min(pair<int, int> a, pair<int, int> b)

{

    return (a > b) ? b : a;

}



int n, ar[200001];

pair<int, int> t[800001][2];



void build(int tl, int tr, int v)

{

    if(tr == tl)

    {

        t[v][tl % 2].fr = ar[tl];

        t[v][(tl + 1) % 2].fr = 1e9;

        t[v][0].sc = tr;

        t[v][1].sc = tr;

    }else

    {

        int tm = (tr + tl) >> 1;

        build(tl, tm, v + v);

        build(tm + 1, tr, v + v + 1);



        t[v][1] = min(t[v + v][1], t[v + v + 1][1]);

        t[v][0] = min(t[v + v][0], t[v + v + 1][0]);

    }

}



pair<int, int> get(int tl, int tr, int l, int r, int v, int num)

{

    if(l > r)

        return mk(1e9, 0);

    if(tr == r && tl == l)

        return t[v][num];

    else

    {

        int tm = (tr + tl) >> 1;

        return min(get(tl, tm, l, min(tm, r), v + v, num), get(tm + 1, tr, max(l, tm + 1), r, v + v + 1, num));

    }

}



int timer = 0, sz[200001], p[200001];

vector<int> vec[100001];

pair<int, int> ars[200001];



void f(int l, int r)

{

    vector<pair<int, int> > ans;

    if(l > r)

        return;



    timer++;

    int x = timer;



    int a, b;

    a = get(1, n, l, r, 1, l % 2).sc;

    b = get(1, n, a + 1, r, 1, (l + 1) % 2).sc;



    ars[timer] = mk(ar[a], ar[b]);

    if(l < a - 1)

        vec[x].push_back(timer + 1), p[timer + 1] = x, f(l, a - 1), sz[x]++;

    if(a + 1 < b - 1)

        p[timer + 1] = x, vec[x].push_back(timer + 1), f(a + 1, b - 1), sz[x]++;

    if(b + 1 < r)

        p[timer + 1] = x, vec[x].push_back(timer + 1), f(b + 1, r), sz[x]++;

}



int main()

{

    sz[0] = 5;

    cin >> n;

    for(int i = 1; i <= n; i++)

        cin >> ar[i];



    build(1, n, 1);



    vector<pair<int, int> > ans;

    f(1, n);

    int inf = 1e9;

    set<pair<pair<int, int>, int> > st;

    st.insert(mk(ars[1], 1));

    while(!st.empty())

    {

        pair<pair<int, int>, int> k = *st.begin();

        st.erase(k);

        for(int i = 0; i < vec[k.sc].size(); i++)

        {

            int to = vec[k.sc][i];

            st.insert(mk(ars[to], to));

        }

        ans.push_back(k.fr);

    }



    //reverse(ans.begin(), ans.end());



    for(int i = 0; i < ans.size(); i++)

        cout << ans[i].fr << " " << ans[i].sc << " ";

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.582911801734743x):
#include<bits/stdc++.h>

using namespace std;

const int Max_N=4*1e5;

int N,A[Max_N+10]={},Del[Max_N+10]={};

pair<int,int> B[Max_N+10]={};

inline int lowbit(int x){

	return x & - x;

}

inline void ADD(int x,int k){

	for(;x;x-=lowbit(x)) Del[x]=min(Del[x],k);

}

inline int ASK(int x){

	int Min=Del[x];

	for(;x<=N;x+=lowbit(x)) Min=min(Min,Del[x]);

	return Min;

}

struct kk{

	int l,r,Id1,Id2,Rev;

} T[Max_N*4+10]={};

inline void Build(int x,int l,int r){

	T[x].l=l; T[x].r=r;

	if(l==r){

		if(l%2) T[x].Id1=l;

		else T[x].Id2=l;

		return;

	}

	Build(x<<1,l,(l+r)>>1);

	Build((x<<1)+1,((l+r)>>1)+1,r);

	T[x].Id1=A[T[x<<1].Id1]<A[T[(x<<1)+1].Id1]?T[x].Id1=T[x<<1].Id1:T[x].Id1=T[(x<<1)+1].Id1;

	T[x].Id2=A[T[x<<1].Id2]<A[T[(x<<1)+1].Id2]?T[x].Id2=T[x<<1].Id2:T[x].Id2=T[(x<<1)+1].Id2;

}

inline void DownTag(int x){

	if(T[x].Rev){

		swap(T[x<<1].Id1,T[x<<1].Id2);

		swap(T[(x<<1)+1].Id1,T[(x<<1)+1].Id2);

		T[x<<1].Rev^=1; T[(x<<1)+1].Rev^=1;

		T[x].Rev=0;

	}

}

inline void Add(int x,int k,int Val){

	DownTag(x);

	if(T[x].l==T[x].r){

		A[k]=Val;

		return;

	}

	if(k<=T[x<<1].r) Add(x<<1,k,Val);

	else Add((x<<1)+1,k,Val);

	T[x].Id1=A[T[x<<1].Id1]<A[T[(x<<1)+1].Id1]?T[x].Id1=T[x<<1].Id1:T[x].Id1=T[(x<<1)+1].Id1;

	T[x].Id2=A[T[x<<1].Id2]<A[T[(x<<1)+1].Id2]?T[x].Id2=T[x<<1].Id2:T[x].Id2=T[(x<<1)+1].Id2;

}

inline void Change(int x,int l,int r){

	if(l<=T[x].l&&T[x].r<=r){

		swap(T[x].Id1,T[x].Id2);

		T[x].Rev^=1;

		return;

	}

	DownTag(x);

	if(l<=T[x<<1].r) Change(x<<1,l,r);

	if(r>T[x<<1].r) Change((x<<1)+1,l,r);

	T[x].Id1=A[T[x<<1].Id1]<A[T[(x<<1)+1].Id1]?T[x].Id1=T[x<<1].Id1:T[x].Id1=T[(x<<1)+1].Id1;

	T[x].Id2=A[T[x<<1].Id2]<A[T[(x<<1)+1].Id2]?T[x].Id2=T[x<<1].Id2:T[x].Id2=T[(x<<1)+1].Id2;

}

inline int Ask(int x,int l,int r,int Opt){

    DownTag(x);

	if(l<=T[x].l&&T[x].r<=r) return Opt==1?T[x].Id1:T[x].Id2;

	int Ans=0,Anss=0;

	if(l<=T[x<<1].r) Ans=Ask(x<<1,l,r,Opt);

	if(r>T[x<<1].r) Anss=Ask((x<<1)+1,l,r,Opt);

	if(A[Ans]>A[Anss]) Ans=Anss;

	return Ans;

}

inline void Solv(){

	for(int i=1;i<=N/2;i++){

		int Min=Ask(1,1,N,1);

		int r=ASK(Min);

		int Minn=Ask(1,Min,r,2);

//		cout<<Min<<' '<<Minn<<' '<<r<<endl;

		B[i]=make_pair(A[Min],A[Minn]);

		Add(1,Min,1<<30); Add(1,Minn,1<<30);

		if(Min+1<Minn-1) Change(1,Min+1,Minn-1);

		ADD(Min,Min); ADD(Minn,Minn);

	}

}

int main(){

	scanf("%d",&N); A[0]=1<<30;

	for(int i=1;i<=N;i++) scanf("%d",&A[i]);

	for(int i=0;i<=N;i++) Del[i]=N;

	Build(1,1,N); Solv();

	for(int i=1;i<=N/2;i++) printf("%d %d ",B[i].first,B[i].second); puts("");

	return 0;

}