// Original C++ solution (slower):
#include <stdio.h>

#include <iostream>

#include <cstdlib>

#include <cmath>

#include <cctype>

#include <string>

#include <cstring>

#include <algorithm>

#include <stack>

#include <queue>

#include <set>

#include <map>

#include <ctime>

#include <vector>

#include <fstream>

#include <list>

#include <iomanip>

#include <numeric>

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

#define ms(s) memset(s, 0, sizeof(s))

const int INF = 1e9;

inline int read(){

	int X = 0,w = 0 ;

	char ch = 0;

	while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}

	while(isdigit(ch)) X = (X<<3) + (X<<1) + (ch ^ 48),ch = getchar();

	return w ? -X : X;

}

int n;

int m=1;

int a[800005];

int seg[2][800005];

int ans[200005];

struct node

{

	int a,b;

	int mint;

};

void update(int k)

{

	int odd;

	int pos=k;

	odd=k%2;

	k+=m-1;

	seg[odd][k]=pos;

	seg[(odd+1)%2][k]=INF;

	while(k>1)

	{

		k/=2;

		for(int i=0;i<2;i++)

		{

			if(seg[i][k*2]==INF and seg[i][k*2+1]!=INF)

			{

				seg[i][k]=seg[i][k*2+1];

			}

			else if(seg[i][k*2+1]==INF&&seg[i][k*2]!=INF)

			{

				seg[i][k]=seg[i][k*2];

			}

			else if(seg[i][k*2]!=INF&&seg[i][k*2+1]!=INF)

			{

				if(a[seg[i][k*2]]<a[seg[i][k*2+1]])

				{

					seg[i][k]=seg[i][k*2];

				}

				else

				{

					seg[i][k]=seg[i][k*2+1];

				}

			}

		}

	}

}

int query(int l,int r,int k,int l1,int r1)

{

	int odd=l%2;

	if(l<=l1 and r>=r1)

	{

		return seg[odd][k];

	}

	if(r<l1 or l>r1)

	{

		return INF;

	}

	else

	{

		int x=query(l,r,k*2,l1,(l1+r1)/2);

		int y=query(l,r,k*2+1,(l1+r1+1)/2,r1);

		if(x==INF and y!=INF)

		{

			return y;

		}

		else if(x!=INF and y==INF)

		{

			return x;

		}

		else if(x==INF and y==INF)

		{

			return INF;

		}

		else

		{

			if(a[x]<a[y])

			{

				return x;

			}

			else

			{

				return y;

			}

		}

	}

}

bool operator >(node x,node y)

{

	if(x.mint!=INF and y.mint!=INF)

	{

		return a[x.mint]>a[y.mint];

	}

	else if(x.mint==INF and y.mint!=INF)

	{

		return true;

	}

	else if(x.mint!=INF and y.mint==INF)

	{

		return false;

	}

	return true;

}

int main()

{

	cin>>n;

	for(int i=0;i<800000;i++)

	{

		a[i]=INF;

		seg[0][i]=INF;

		seg[1][i]=INF;

	}

	while(m<n)

	{

		m*=2;

	}

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

	{

		cin>>a[i];

	}

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

	{

		update(i);

	}

	priority_queue<node,vector<node>,greater<node> > pq;

	node init={1,n,query(1,n,1,1,m)};

	pq.push(init);

	int id=1;

	while(id<=n and !pq.empty())

	{

		node f=pq.top();

		pq.pop();

		ans[id++]=f.mint;

		int tmp=query(f.mint+1,f.b,1,1,m);

		node nx,dx={f.mint+1,f.b,tmp};

		if(f.a<f.mint-1)

		{

			tmp=query(f.a,f.mint-1,1,1,m);

			nx={f.a,f.mint-1,tmp};

			pq.push(nx);

		}

		ans[id++]=dx.mint;

		node sec,thir;

		if(dx.a<dx.mint-1)

		{

			tmp=query(dx.a,dx.mint-1,1,1,m);

			sec={dx.a,dx.mint-1,tmp};

			pq.push(sec);

		}

		if(dx.mint+1<dx.b)

		{

			tmp=query(dx.mint+1,dx.b,1,1,m);

			thir={dx.mint+1,dx.b,tmp};

			pq.push(thir);

		}

	}

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

	{

		cout<<a[ans[i]]<<" ";

	}

	return 0;

}

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

using namespace std;



const int N = 2e5 + 10;

int n, a[N], t[2][N << 2];



inline int read() {

	int s = 0, f = 1;

	char ch;

	for(; ch < '0' || ch > '9'; ch = getchar())	if(ch == '-')	f = -1;

	for(; ch >= '0' && ch <= '9'; ch = getchar())	s = (s << 1) + (s << 3) + ch - '0';

	return s * f;

}



inline void add(int o, int pos, int l, int r, int cnt) {

	if (a[cnt] < a[t[o][pos]])	t[o][pos] = cnt;

	if (l == r)	return;

	int mid = (l + r) >> 1;

	if (cnt <= mid)	add(o, pos << 1, l, mid, cnt);

	else	add(o, pos << 1 | 1, mid + 1, r, cnt);

}



inline int ask(int o, int pos, int l, int r, int L, int R) {

	if (l > R || r < L)	return 0;

	if (L <= l && r <= R)	return t[o][pos];

	int mid = (l + r) >> 1;

	int lans = ask(o, pos << 1, l, mid, L, R);

	int rans = ask(o, pos << 1 | 1, mid + 1, r, L, R);

	return a[lans] < a[rans] ? lans : rans;

}



struct node {

	int l, r, v;

	node() {}

	node(int _l, int _r){ l = _l, r = _r, v = l > r ? 0 : ask(l & 1, 1, 1, n, l, r); }

	friend bool operator < (node A,node B) { return a[A.v] < a[B.v]; }

};



set <node> s;



int main() {

	n = read();

	a[0] = n + 1;

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

		a[i] = read();

		add(i & 1, 1, 1, n, i);

	}

	s.clear();

	s.insert(node(1, n));

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

		node now = *s.begin();

		s.erase(s.begin());

		int l = now.l, r = now.r;

		int lmid = now.v, rmid = ask((lmid & 1) ^ 1, 1, 1, n, lmid, r);

		printf("%d %d ", a[lmid], a[rmid]);

		s.insert(node(l, lmid - 1));

		s.insert(node(lmid + 1, rmid - 1));

		s.insert(node(rmid + 1, r));

	}

	puts("");

	return 0;

}


// Fastest known solution for this problem: