#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <bitset>
#include <ctime>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define F first
#define S second
#define qq queue
#define dq deque
#define vc vector
#define INF ((int)(1e9))
#define in cin >>
#define LINF ((int)(1e18))
#define out cout <<
#define ln  << endl
#define pb push_back
#define mp make_pair
#define ll long long
#define _tp template
#define _tyn typename
#define pf push_front
#define itor iterator
#define sint short int
#define ull unsigned ll
#define pq priority_queue
#define pii pair<int,int>
#define uint unsigned int
#define B out "BreakPoint\n";
#define read(_num) scanf("%d",&_num)
#define ms(_data) memset(_data,0,sizeof(_data))
#define fin(_filename) freopen(_filename,"r",stdin)
#define fout(_filename) freopen(_filename,"w",stdout)
#define read2(_num1,_num2) scanf("%d %d",&_num1,&_num2)
#define msn(_data,_num) memset(_data,_num,sizeof(_data))
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);
#define read3(_num1,_num2,_num3) scanf("%d %d %d",&_num1,&_num2,&_num3)
using namespace std;
_tp<_tyn T>void mymax( T &_a , T _b ){ if( _a < _b ) _a = _b; }
_tp<_tyn T>void mymin( T &_a , T _b ){ if( _a > _b ) _a = _b; }
_tp<_tyn T>void print(T _x){
for(auto _it=_x.begin();_it!=_x.end();_it++)
cout<<*_it<<" ";cout ln;}
void print(int _x){printf("%d ",_x);}
void print(ll _x){printf("%lld ",_x);}
void delay(ll _time){
for(ll _i=1;_i<=10000000000*_time;_i++)
for(ll _j=1;_j<=10000000000*_time;_j++);}
#define MAXN 200010

int n;
int inp[MAXN];

struct Node{
	int id , val;
	Node(){
		id = 0;
		val = INF;
	}
	Node( int iid , int vall ){
		id = iid; val = vall;
	}
};
bool operator<( Node n1 , Node n2 ){
	return n1.val < n2.val;
}
bool operator>( Node n1 , Node n2 ){
	return n1.val > n2.val;
}

struct Rmq{
	Node tree[MAXN*4];
	bool sw;	//  1:odd  0:even
	Rmq(){ sw = 0; }
	Rmq( bool ssw ){ sw = ssw; }
	void update( int pos ){
		tree[pos] = min( tree[ pos << 1 ] , tree[ pos << 1 | 1 ] );
	}
	void build( int l , int r , int pos ){
		if( l == r ){
			if( sw == (l & 1) )
				tree[pos] = Node( l , inp[l] );
			else
				tree[pos] = Node( 0 , INF );
		}else{
			int mid = (l+r) >> 1;
			build( l , mid , pos << 1 );
			build( mid+1 , r , pos << 1 | 1 );
			update( pos );
		}
	}
	Node query( int gl , int gr , int l , int r , int pos ){
		if( gl <= l  &&  r <= gr ) return tree[pos];
		int mid = (l+r) >> 1;
		Node ans1 = Node( 0 , INF) , ans2 = Node( 0 , INF);
		if( gl <= mid ) ans1 = query( gl , gr , l , mid , pos << 1 );
		if( gr > mid ) ans2 = query( gl , gr , mid+1 , r , pos << 1 | 1 );
		return min( ans1 , ans2 );
	}
	Node query( int gl , int gr ){	// [ gl , gr ]
		return query( gl , gr , 1 , n , 1 );
	}
};
Rmq odd=Rmq(1) , even=Rmq(0);

struct Inl{
	int l; int r;
	Node minval;
	Inl(){}
	Inl( int ls , int rs ){			//[ ls , rs ]
		l = ls;
		r = rs;
		if( l > r ) return;
		if( ls % 2 )
			minval = odd.query( ls , rs );
		else
			minval = even.query( ls , rs );
	}
	bool ok(){
		return l <= r;
	}
};
bool operator<( Inl i1 , Inl i2 ){
	return i1.minval > i2.minval;
}
pq<Inl> q;

int main(){
	//fin( "E.txt" );
	
	read( n );
	for( int i = 1 ; i <= n ; i++ )
		read( inp[i] );
		
	odd.build( 1 , n , 1 );
	even.build( 1 , n , 1 );
	q.push( Inl( 1 , n ) );
	
	//int cnt = 0;
	while( !q.empty() ){
		Inl now = q.top();
		q.pop();
		Node boyfriend = now.minval;
		Node girlfriend = Node();
		
		if( (boyfriend.id & 1)==0 ) girlfriend = odd.query( boyfriend.id+1 , now.r );
		else girlfriend = even.query( boyfriend.id+1 , now.r );
		printf( "%d %d " , boyfriend.val , girlfriend.val );
		//break;
		Inl needtodo[] = {
			Inl( now.l , boyfriend.id-1 ),
			Inl( boyfriend.id+1 , girlfriend.id-1 ),
			Inl( girlfriend.id+1 , now.r )
		};
		
		for( int i = 0 ; i < 3 ; i++ ){
			Inl nowdo = needtodo[i];
			if( !nowdo.ok() ) continue;
			q.push( nowdo );
		}
		//cnt++;
		//if( cnt > 10 ) break;
	}
	
	
	return 0;
}

Measured memory_bytes: 15604