// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define rep(i,x,y) for (int i=(x); i<=(y); i++)

#define ll long long

#define ld long double

#define inf 1000000000

using namespace std;

ll read(){

	char ch=getchar(); ll x=0; int op=1;

	for (; !isdigit(ch); ch=getchar()) if (ch=='-') op=-1;

	for (; isdigit(ch); ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';

	return x*op;

}

#define N 200005

#define lc (o<<1)

#define rc (o<<1|1)

int n,a[N],tr[2][N<<1];

int Min(int x,int y){ return a[x]<a[y]?x:y; }

void up(int typ,int o){ tr[typ][o]=Min(tr[typ][lc],tr[typ][rc]); }

void build(int typ,int o,int l,int r){

	if (l==r){ tr[typ][o]=2*l-typ; return; }

	int mid=l+r>>1;

	build(typ,lc,l,mid); build(typ,rc,mid+1,r);

	up(typ,o);

}

int qry(int typ,int o,int l,int r,int x,int y){

	if (x<=l && r<=y) return tr[typ][o];

	int mid=l+r>>1,ret=0;

	if (x<=mid) ret=Min(ret,qry(typ,lc,l,mid,x,y));

	if (y>mid) ret=Min(ret,qry(typ,rc,mid+1,r,x,y));

	return ret;

}

void modify(int typ,int o,int l,int r,int x){

	if (l==r){ a[l]=inf; return; }

	int mid=l+r>>1;

	if (x<=mid) modify(typ,lc,l,mid,x); else modify(typ,rc,mid+1,r,x);

	up(typ,o);

}

struct node{

	int l,r,x,y,tg; node(){}

	node(int l_,int r_,int tg_){

		l=l_,r=r_,tg=tg_;

		if (l+1==r) x=l,y=r;

		else{

			if (!tg) x=qry(tg^1,1,1,n/2,(l+1)/2,r/2),y=qry(tg,1,1,n/2,(x+1)/2,r/2);

			else x=qry(tg^1,1,1,n/2,(l+1)/2,r/2),y=qry(tg,1,1,n/2,(x+2)/2,(r+1)/2);

			//cerr<<(l+1)/2<<' '<<(r+1)/2<<endl;

			

			//cerr<<"["<<l<<","<<r<<"]: x="<<x<<", y="<<y<<endl;

		}

	}

	bool operator < (const node &t) const{ return a[x]>a[t.x]; }

};

priority_queue<node> q;

void ins(int x,int y,int tg){ if (x<y) q.push(node(x,y,tg)); }

int main(){

	n=read();

	rep (i,1,n) a[i]=read(); a[0]=inf;

	build(1,1,1,n/2); build(0,1,1,n/2);

	q.push(node(1,n,0));

	rep (step,1,n/2){

		node tmp=q.top(); q.pop();

		printf("%d %d ",a[tmp.x],a[tmp.y]);

		//cerr<<tmp.x<<' '<<tmp.y<<endl;

		ins(tmp.l,tmp.x-1,tmp.tg);//1,2

		//cerr<<"ins: ";

		//cerr<<tmp.l<<' '<<tmp.x-1<<endl;

		ins(tmp.x+1,tmp.y-1,tmp.tg^1);//4,7

		//cerr<<tmp.x+1<<' '<<tmp.y-1<<endl;

		ins(tmp.y+1,tmp.r,tmp.tg);//9,8

		//cerr<<tmp.y+1<<' '<<tmp.r<<endl;

		//cerr<<"===="<<endl;

	}

	return 0;

}

/*

4

3 2 4 1

8

4 6 3 2 8 5 7 1

*/

// Fastest known solution for this problem: