//单调栈结构(进阶)
//https://www.nowcoder.com/practice/2a2c00e7a88a498693568cef63a4b7bb

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6+10;

int arr[N];
int stk[N];
int ans[N][2];
int top=0;//栈顶
int n=0;//arr元素个数
int pop=0;//当前弹出的位置

void compute()
{
//一、入栈阶段:
    //遍历:严格大压小,将不合适的元素弹出占中,此时弹出的元素的左右答案已经找到,只剩下弹栈完后的栈中元素的左右答案还未找到
    for(int i=0 ; i<n ; i++)
    {
        //一阶弹栈:入栈时遇到小于或等于栈中元素时弹栈
        //弹栈可以结算答案
        while( (top > 0) && (arr[i] <= arr[stk[top-1]]) )
        {
            //将要弹栈的下标:pop
            pop = stk[--top];//当前要被弹出的元素下标
            //ans[pop][0]:结算左边 | ans[pop][1]:结算右边
            ans[pop][0] = top > 0 ? stk[top-1] : -1; //判断当前元素地下还有没有数
            ans[pop][1] = i;
        }
        //将大于等于当前元素的元素全部弹栈之后 , 将当前元素入栈
        stk[top++] = i;
    }

//二、弹栈阶段(二阶弹栈) 
    //清算阶段:将栈中的元素找到左右答案
    //将栈中的下标一次弹出
    while(top > 0) // top > 0 栈里有元素
    {
        pop = stk[--top];
        ans[pop][0] = top > 0 ? stk[top-1] : -1;
        ans[pop][1] = -1;
    }

//三、修正阶段:从右往左遍历 
    //针对右答案 如果右答案的值与当前元素的值相同时,将右答案的右答案作为自己的右答案
    for(int i=n-2 ; i>=0 ; i--)
    {
        if( (ans[i][1] != -1) && (arr[ans[i][1]] == arr[i]) )
        {
            ans[i][1] = ans[ans[i][1]][1];
        }
    }
}

int main()
{
    scanf("%d" , &n);
    for(int i=0 ; i<n ; i++)
    {
        scanf("%d" , &arr[i]);
    }

    compute();

    for(int i=0 ; i<n ; i++)
    {
        printf("%d %d\n" , ans[i][0] , ans[i][1]);
    }

    return 0;
}