Ivan has an array consisting of n different integers. He decided to reorder all elements in increasing order. Ivan loves merge sort so he decided to represent his array with one or several increasing sequences which he then plans to merge into one sorted array.

Ivan represent his array with increasing sequences with help of the following algorithm.

While there is at least one unused number in array Ivan repeats the following procedure:

  * iterate through array from the left to the right; 
  * Ivan only looks at unused numbers on current iteration; 
  * if current number is the first unused number on this iteration or this number is greater than previous unused number on current iteration, then Ivan marks the number as used and writes it down. 



For example, if Ivan's array looks like [1, 3, 2, 5, 4] then he will perform two iterations. On first iteration Ivan will use and write numbers [1, 3, 5], and on second one — [2, 4].

Write a program which helps Ivan and finds representation of the given array with one or several increasing sequences in accordance with algorithm described above.

Input

The first line contains a single integer n (1 ≤ n ≤ 2·105) — the number of elements in Ivan's array.

The second line contains a sequence consisting of distinct integers a1, a2, ..., an (1 ≤ ai ≤ 109) — Ivan's array.

Output

Print representation of the given array in the form of one or more increasing sequences in accordance with the algorithm described above. Each sequence must be printed on a new line.

Examples

Input

5
1 3 2 5 4


Output

1 3 5 
2 4 


Input

4
4 3 2 1


Output

4 
3 
2 
1 


Input

4
10 30 50 101


Output

10 30 50 101 
import java.io.*;

import java.util.*;

public class Two {
    static class Parser {
            final private int BUFFER_SIZE = 1 << 16;
            private DataInputStream din;
            private byte[] buffer;
            private int bufferPointer, bytesRead;

            public Parser(InputStream in) {
                din = new DataInputStream(in);
                buffer = new byte[BUFFER_SIZE];
                bufferPointer = bytesRead = 0;
            }

            public long nextLong() throws Exception {
                long ret = 0;
                byte c = read();
                while (c <= ' ') c = read();
                boolean neg = c == '-';
                if (neg) c = read();
                do {
                    ret = ret * 10 + c - '0';
                    c = read();
                } while (c > ' ');
                if (neg) return -ret;
                return ret;
            }

            //reads in the next string
            public String next() throws Exception {
                StringBuilder ret = new StringBuilder();
                byte c = read();
                while (c <= ' ') c = read();
                do {
                    ret = ret.append((char) c);
                    c = read();
                } while (c > ' ');
                return ret.toString();
            }

            public int nextInt() throws Exception {
                int ret = 0;
                byte c = read();
                while (c <= ' ') c = read();
                boolean neg = c == '-';
                if (neg) c = read();
                do {
                    ret = ret * 10 + c - '0';
                    c = read();
                } while (c > ' ');
                if (neg) return -ret;
                return ret;
            }

            private void fillBuffer() throws Exception {
                bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1) buffer[0] = -1;
            }

            private byte read() throws Exception {
                if (bufferPointer == bytesRead) fillBuffer();
                return buffer[bufferPointer++];
            }
        }

        static class Edge implements Comparable<Edge> {
            int u, v;

            Edge(int u, int v) {
                this.u = u;
                this.v = v;
            }

            public int compareTo(Edge other) {
                if (this.u == other.u) {
                    return this.v - other.v;
                }
                return this.u - other.u;
            }
        }

        static class Point{
            int in,val;
            Point(int in,int val){
                this.in=in;
                this.val=val;
            }
        }
        static class Node{
            int val;
            Node left;
            Node right;
            Node(int val){
                this.val=val;
                this.left=null;
                this.right=null;
            }
        }

    static int ax[]={0,0,-1,1};
    static int ay[]={-1,1,0,0};

    static Point special=new Point(-1,Integer.MAX_VALUE);
    public static void main(String args[]) throws Exception {
        Parser pr = new Parser(System.in);
        //BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        //Scanner sc=new Scanner(System.in);
        //FastReader fr=new FastReader();
        PrintWriter out = new PrintWriter(System.out);
        int n;
        n=pr.nextInt();
        int ran[]=new int[n];
        int arr[]=new int[n];
        for(int i=0;i<n;i++){
            ran[i]=pr.nextInt();
        }
        compress(ran,arr);
        //System.out.println(Arrays.toString(arr));
        int indexes[]=new int[n];
        for(int i=0;i<n;i++){
            indexes[arr[i]]=i;
        }
        Point pt[]=new Point[n];

        for(int i=0;i<n;i++){
            pt[i]=new Point(i,indexes[i]);
        }

        //System.out.println(Arrays.toString(indexes));

        SegmentTreeRMQ sg=new SegmentTreeRMQ();
        sg.constructST(pt,n);

        //SegmentTree sg=new SegmentTree(n,indexes);
        //sg.build(indexes,0,n-1,0);
        //int ans=sg.query(indexes,0,n-1,0,n-1,0);
        //System.out.println(indexes[ans]);
        ArrayList<ArrayList<Integer>> list=new ArrayList<>();

        while(true){
            Point start=sg.RMQ(n,0,n-1);
            int st=start.in;
            //System.out.println(start.in+" k "+start.val);
            if(start.val==Integer.MAX_VALUE){
                break;
            }
            else{
                ArrayList<Integer> x=new ArrayList<>();
                x.add(ran[start.val]);

                //System.out.println(start.in+"k");
                sg.update(0,n-1,start.in,Integer.MAX_VALUE,0);

                indexes[start.in]=Integer.MAX_VALUE;
                /*if(start.in==0){
                    System.out.println("here");
                    int ans=sg.RMQ(n,0,n-1);
                    System.out.println(ans);
                }*/

                while(true){

                    if(st == n-1){
                        //System.out.println(st+" x "+n);
                        break;
                    }
                    //System.out.println((st)+ " hlag");
                    start=sg.RMQ(n,st+1,n-1);
                    st=start.in;
                    //System.out.println(st+" gha");
                    if(start.val == Integer.MAX_VALUE)
                        break;
                    x.add(ran[start.val]);
                    //System.out.println(start.in+"j");
                    sg.update(0,n-1,start.in,Integer.MAX_VALUE,0);
                    indexes[start.in]=Integer.MAX_VALUE;
                }
                list.add(x);
            }

        }

        for(ArrayList<Integer> x : list){
            for(int num : x){
                out.print(num+" ");
            }
            out.println();
        }
        //System.out.println(Arrays.toString(indexes));
        out.close();
    }

    static void compress(int ran[],int arr[]){
        int n=ran.length;
        int exc[][]=new int[n][2];
        for(int i=0;i<n;i++){
            exc[i][0]=ran[i];
            exc[i][1]=i;
        }
        Arrays.sort(exc, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0]-o2[0];
            }
        });

        int start=0;
        for(int i=0;i<n;i++){
            int index=exc[i][1];
            arr[index]=start;
            start++;
        }
    }
    static int getRight(int s,Node arr[]){
        Node cur=arr[s];
        while(cur.right !=null){
            cur=cur.right;
        }
        return cur.val;
    }

    static long gcd(long a,long b){
        if(b==0){
            return a;
        }
        return gcd(b,a%b);
    }

    // Program for range minimum query using segment tree
    static class SegmentTreeRMQ
    {
        Point st[]; //array to store segment tree

        // A utility function to get minimum of two numbers
        Point minVal(Point x, Point y) {
            return (x.val < y.val) ? x : y;
        }

        // A utility function to get the middle index from corner
        // indexes.
        int getMid(int s, int e) {
            return s + (e - s) / 2;
        }

        /*  A recursive function to get the minimum value in a given
            range of array indexes. The following are parameters for
            this function.

            st    --> Pointer to segment tree
            index --> Index of current node in the segment tree. Initially
                       0 is passed as root is always at index 0
            ss & se  --> Starting and ending indexes of the segment
                         represented by current node, i.e., st[index]
            qs & qe  --> Starting and ending indexes of query range */
        Point RMQUtil(int ss, int se, int qs, int qe, int index)
        {
            // If segment of this node is a part of given range, then
            // return the min of the segment
            if (qs <= ss && qe >= se)
                return st[index];

            // If segment of this node is outside the given range
            if (se < qs || ss > qe)
                return special;

            // If a part of this segment overlaps with the given range
            int mid = getMid(ss, se);
            return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
                    RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
        }

        // Return minimum of elements in range from index qs (quey
        // start) to qe (query end).  It mainly uses RMQUtil()
        Point RMQ(int n, int qs, int qe)
        {
            // Check for erroneous input values
            if (qs < 0 || qe > n - 1 || qs > qe) {
                System.out.println("Invalid Input");
                return null;
            }

            return RMQUtil(0, n - 1, qs, qe, 0);
        }

        // A recursive function that constructs Segment Tree for
        // array[ss..se]. si is index of current node in segment tree st
        Point constructSTUtil(Point arr[], int ss, int se, int si)
        {
            // If there is one element in array, store it in current
            //  node of segment tree and return
            if (ss == se) {
                st[si] = arr[ss];
                return arr[ss];
            }

            // If there are more than one elements, then recur for left and
            // right subtrees and store the minimum of two values in this node
            int mid = getMid(ss, se);
            st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
                    constructSTUtil(arr, mid + 1, se, si * 2 + 2));
            return st[si];
        }

        void update(int ss,int se,int i,int val,int si)
        {
            if(i<ss || i>se)
                return;
            if(ss==se){
                st[si].val=val;
                return;
            }
            int mid=getMid(ss,se);
            update(ss,mid,i,val,si*2+1);
            update(mid+1,se,i,val,si*2+2);
            if(st[si*2+1].val <= st[si*2+2].val){
                st[si]=st[si*2+1];
            }
            else{
                st[si]=st[si*2+2];
            }
            //st[n] = Math.min( st[n*2] , st[n*2 + 1] );

        }

        /* Function to construct segment tree from given array. This function
           allocates memory for segment tree and calls constructSTUtil() to
           fill the allocated memory */
        void constructST(Point arr[], int n)
        {
            // Allocate memory for segment tree

            //Height of segment tree
            int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

            //Maximum size of segment tree
            int max_size = 2 * (int) Math.pow(2, x) - 1;
            st = new Point[max_size]; // allocate memory

            // Fill the allocated memory st
            constructSTUtil(arr, 0, n - 1, 0);
        }

        // Driver program to test above functions
        /*
        public static void main(String args[])
        {
            int arr[] = {1, 3, 2, 7, 9, 11};
            int n = arr.length;
            SegmentTreeRMQ tree = new SegmentTreeRMQ();

            // Build segment tree from given array
            tree.constructST(arr, n);

            int qs = 1;  // Starting index of query range
            int qe = 5;  // Ending index of query range

            // Print minimum value in arr[qs..qe]
            System.out.println("Minimum of values in range [" + qs + ", "
                    + qe + "] is = " + tree.RMQ(n, qs, qe));
        }
        */
    }
// This code is contributed by Ankur Narain Verma


    static class SegmentTree{
        int st[];
        int size;
        SegmentTree(int n,int val[]){
            int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
            int size = 2 * (int) Math.pow(2, x) - 1;
            st=new int[size];
            build(val,0,n-1,0);
        }

        void update(int root, int b, int e, int idx, int val)
        {
            if (b>e || b>idx || e<idx ) return;
            if (b==e) //at leaf node
            {

                st[root] = val;
                /*if(b==0){
                    System.out.println("here "+st[n]);
                }*/
                return;
            }

            update( root*2 , b , (b+e)/2 , idx, val );
            update( root*2 + 1 , (b+e)/2 + 1 , e , idx, val );

            //now some change might have been made in either of the child nodes.

            st[root] = Math.min( st[root*2] , st[root*2 + 1] );

        }

        int build(int val[],int l,int r,int root){
            if(l==r){
                st[root]=l;
                return st[root];
            }
            int mid=l+(r-l)/2;
            int left=build(val,l,mid,2*root+1);
            int right=build(val,mid+1,r,2*root+2);
            if(val[left]<=val[right]){
                st[root]=left;
            }
            else{
                st[root]=right;
            }
            return st[root];
        }

        int query(int val[],int l,int r,int s,int e,int root){
            //System.out.println(l+" "+r+" "+s+" "+e);
            if(s<=l && e>=r){
                //System.out.println(s+" "+e+"hree");
                return st[root];
            }
            if(r<s || l>e){

                return -1;
            }
            int mid=l+(r-l)/2;
            int left=query(val,l,mid,s,e,2*root+1);
            int right=query(val,mid+1,r,s,e,2*root+2);
            if(left==-1){
                st[root]=right;
            }
            else if(right==-1){
                st[root]=left;
            }
            else if(val[left]<=val[right]){
                st[root]=left;
            }
            else if(val[right]<=val[left]){
                st[root]=right;
            }

            return st[root];
        }
    }


}