#include <bits/stdc++.h>

using namespace std;

#define rep(i, t) for(ll (i) = 0; (i) < (ll)(t); (i)++)
#define reu(i, s, e) for(ll (i) = (ll)(s); (i) <= (ll)(e); (i)++)
#define rer(i, s, e) for(ll (i) = (ll)(s); (i) < (ll)(e); (i)++)
#define For(i, v) for(__typeof((v).begin()) (i) = (v).begin(); (i) != (v).end(); (i) ++)
#define mset(arr, val) memset(arr, (val), sizeof arr)
#define PB push_back
#define MP make_pair
#define p1 first
#define p2 second

typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<int, int> pie;

const int maxn = 2e5 + 10;
int af[maxn], bf[maxn], sf[maxn];
int Ta[4 * maxn], Tb[4 * maxn], Ts[4 * maxn];
int s[maxn];

int F(int *T, int L, int R, int id, int idx){
    T[id] ++;
    if(R - L == 1)
        return 0;
    int mid = (L + R) >> 1;
    if(idx < mid)
        return F(T, L, mid, id * 2, idx);
    else
        return F(T, mid, R, id * 2 + 1, idx) + T[id * 2];
}

int G(int L, int R, int id, int idx){
    Ts[id] ++;
    if(R - L == 1){
        return L;
    }
    int mid = (L + R) >> 1;
    if(mid - L - Ts[id * 2] >= idx)
        return G(L, mid, id * 2, idx);
    else
        return G(mid, R, id * 2 + 1, idx - (mid - L - Ts[id * 2]));
}

int main(){
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    int a[n + 1], b[n + 1];
    rep(i, n)
        cin >> a[i];
    rep(i, n)
        cin >> b[i];
    rep(i, n){
        af[n - i - 1] = a[i] - F(Ta, 0, n, 1, a[i]);
        bf[n - i - 1] = b[i] - F(Tb, 0, n, 1, b[i]);
    }

    rep(i, n){
        sf[i] += af[i] + bf[i];
        sf[i + 1] += sf[i] / (i + 1);
        sf[i] %= i + 1;
    }

    for(int i = n - 1; i >= 0; i--)
        s[n - i - 1] = G(0, n, 1, sf[i] + 1);
    rep(i, n)
        cout << s[i] << ' ';
    cout << endl;
    return 0;
}


#include <iostream>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include <string.h>
#include <stdio.h>
#define sf scanf
#define pf printf
#define ll long long

#define clr(x) memset(x,0,sizeof(x))
#define _clr(x) memset(x,-1,sizeof(x))
#define fr(i,a,b) for(int i = a; i < b; ++i )

using namespace std;

int n;

int a[200020], b[200020];
int k1[200020], k2[200020], k3[200020];

ll c[200020];

void add( int t, int d )
{
	++t;
	for( int i = t; i <=n; i += i & -i )
		c[i]+=d;
	//printf("add t = %d d = %d\n",t,d);
}

int sum( int t )
{
	++t;
	int ret = 0;
	for( int i = t; i > 0; i -= i & -i )
		ret += c[i];
	//printf("find t = %d ret = %d\n",t,ret);
	return ret;
}

void init()
{
	clr( c );
	for( int i = 0; i <n; ++i )
		add( i, 1 );
}

void get( int * a, int * k )
{
	init();
	set< int > ft;
	for( int i = 0; i < n; ++i )
	{
		k[i] = sum(a[i]-1);
		add( a[i], -1 );
	}
}

set< int > nima;

int find( int k )
{
	int l = -1, r = n;
	while( l + 1 < r )
	{
		int mid = ( l + r ) >> 1;
		int index = sum( mid );
		//printf("mid = %d index = %d\n",mid, index );
		if( index > k ){
			r = mid;
		}
		else
			l = mid;
	}

//	printf("fid k = %d l = %d\n",k, l);

	add( l+1, -1 );
	return l+1;
}

int ans[200020];

void solve()
{
	clr( k1 );
	clr( k2 );
	clr( k3 );

		get( a, k1 );
		get ( b, k2 );

		/*
		for( int i = n-1; i >=0 ; --i )
		{
			int t = ( k1[i] + k2[i] ) / ( n - i );
			k3[i] = ( k3[i] + k1[i] + k2[i] ) % ( n - i );
			if( t > 0 ) k3[i-1] += t;
			//printf("i = %d k3 = %d\n",i,k3[i]);
		}
		*/

		int ix=0;
		for(int i=n-1;i>=0;i--)
		{
			k3[i]=(k1[i]+k2[i]+ix)%(n-i);
			ix=(k1[i]+k2[i]+ix)/(n-i);
		}

		init();

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

}

int main()
{
	while( cin>>n )
	{
		for( int i = 0; i < n; ++i )
			sf("%d",&a[i]);
		for( int i = 0; i < n; ++ i )
			sf("%d",&b[i]);
	}

	solve();
}


#include <iostream>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include <string.h>
#include <stdio.h>
#define sf scanf
#define pf printf
#define ll long long

#define clr(x) memset(x,0,sizeof(x))
#define _clr(x) memset(x,-1,sizeof(x))
#define fr(i,a,b) for(int i = a; i < b; ++i )

using namespace std;

int n;

int a[200020], b[200020];
int k1[200020], k2[200020], k3[200020];

int c[200020];

void add( int t, int d )
{
    ++t;
    for( int i = t; i <=n; i += i & -i )
        c[i]+=d;
    //printf("add t = %d d = %d\n",t,d);
}

int sum( int t )
{
    ++t;
    int ret = 0;
    for( int i = t; i > 0; i -= i & -i )
        ret += c[i];
    //printf("find t = %d ret = %d\n",t,ret);
    return ret;
}

void init()
{
    clr( c );
    for( int i = 0; i <n; ++i )
        add( i, 1 );
}

void get( int * a, int * k )
{
    init();
    set< int > ft;
    for( int i = 0; i < n; ++i )
    {
        k[i] = sum(a[i]-1);
        add( a[i], -1 );
    }
}

set< int > nima;

int find( int k )
{
    int l = -1, r = n;
    while( l + 1 < r )
    {
        int mid = ( l + r ) >> 1;
        int index = sum( mid );
        //printf("mid = %d index = %d\n",mid, index );
        if( index > k ){
            r = mid;
        }
        else
            l = mid;
    }

//  printf("fid k = %d l = %d\n",k, l);

    add( l+1, -1 );
    return l+1;
}

int ans[200020];

void solve()
{
    clr( k1 );
    clr( k2 );
    clr( k3 );

        get( a, k1 );
        get ( b, k2 );

        for( int i = n-1; i >=0 ; --i )
        {
            int t = ( k1[i] + k2[i] ) / ( n - i );
            k3[i] = ( k3[i] + k1[i] + k2[i] ) % ( n - i );
            if( t > 0 ) k3[i-1] += t;
            //printf("i = %d k3 = %d\n",i,k3[i]);
        }

        init();

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

}

int main()
{
    while( cin>>n )
    {
        for( int i = 0; i < n; ++i )
            sf("%d",&a[i]);
        for( int i = 0; i < n; ++ i )
            sf("%d",&b[i]);
    }

    solve();
}


#include <iostream>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include <string.h>
#include <stdio.h>
#define sf scanf
#define pf printf
#define ll long long

#define clr(x) memset(x,0,sizeof(x))
#define _clr(x) memset(x,-1,sizeof(x))
#define fr(i,a,b) for(int i = a; i < b; ++i )

using namespace std;

int n;

int a[200020], b[200020];
int k1[200020], k2[200020], k3[200020];

ll c[200020];

void add( int t, int d )
{
    ++t;
    for( int i = t; i <=n; i += i & -i )
        c[i]+=d;
    //printf("add t = %d d = %d\n",t,d);
}

int sum( int t )
{
    ++t;
    int ret = 0;
    for( int i = t; i > 0; i -= i & -i )
        ret += c[i];
    //printf("find t = %d ret = %d\n",t,ret);
    return ret;
}

void init()
{
    clr( c );
    for( int i = 0; i <n; ++i )
        add( i, 1 );
}

void get( int * a, int * k )
{
    init();
    set< int > ft;
    for( int i = 0; i < n; ++i )
    {
        k[i] = sum(a[i]-1);
        add( a[i], -1 );
    }
}

set< int > nima;

int find( int k )
{
    int l = -1, r = n;
    while( l + 1 < r )
    {
        int mid = ( l + r ) >> 1;
        int index = sum( mid );
        //printf("mid = %d index = %d\n",mid, index );
        if( index > k ){
            r = mid;
        }
        else
            l = mid;
    }

//  printf("fid k = %d l = %d\n",k, l);

    add( l+1, -1 );
    return l+1;
}

int ans[200020];

void solve()
{
    clr( k1 );
    clr( k2 );
    clr( k3 );

        get( a, k1 );
        get ( b, k2 );

        for( int i = n-1; i >=0 ; --i )
        {
            int t = ( k1[i] + k2[i] ) / ( n - i );
            k3[i] = ( k3[i] + k1[i] + k2[i] ) % ( n - i );
            if( t > 0 ) k3[i-1] += t;
            //printf("i = %d k3 = %d\n",i,k3[i]);
        }

        init();

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

}

int main()
{
    while( cin>>n )
    {
        for( int i = 0; i < n; ++i )
            sf("%d",&a[i]);
        for( int i = 0; i < n; ++ i )
            sf("%d",&b[i]);
    }

    solve();
}


#include <iostream>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include <string.h>
#include <stdio.h>
#define sf scanf
#define pf printf
#define ll long long

#define clr(x) memset(x,0,sizeof(x))
#define _clr(x) memset(x,-1,sizeof(x))
#define fr(i,a,b) for(int i = a; i < b; ++i )

using namespace std;

int n;

int a[100000], b[100000];
int k1[100000], k2[100000], k3[100000];

int c[100000];

void add( int t, int d )
{
    ++t;
    for( int i = t; i <=n; i += i & -i )
        c[i]+=d;
    //printf("add t = %d d = %d\n",t,d);
}

int sum( int t )
{
    ++t;
    int ret = 0;
    for( int i = t; i > 0; i -= i & -i )
        ret += c[i];
    //printf("find t = %d ret = %d\n",t,ret);
    return ret;
}

void init()
{
    clr( c );
    for( int i = 0; i <n; ++i )
        add( i, 1 );
}

void get( int * a, int * k )
{
    init();
    set< int > ft;
    for( int i = 0; i < n; ++i )
    {
        k[i] = sum(a[i]-1);
        add( a[i], -1 );
    }
}

set< int > nima;

int find( int k )
{
    int l = -1, r = n;
    while( l + 1 < r )
    {
        int mid = ( l + r ) >> 1;
        int index = sum( mid );
        //printf("mid = %d index = %d\n",mid, index );
        if( index > k ){
            r = mid;
        }
        else
            l = mid;
    }

//  printf("fid k = %d l = %d\n",k, l);

    add( l+1, -1 );
    return l+1;
}

int ans[100000];

void solve()
{
    clr( k1 );
    clr( k2 );
    clr( k3 );

        get( a, k1 );
        get ( b, k2 );

        for( int i = n-1; i >=0 ; --i )
        {
            int t = ( k1[i] + k2[i] ) / ( n - i );
            k3[i] = ( k3[i] + k1[i] + k2[i] ) % ( n - i );
            if( t > 0 ) k3[i-1] += t;
            //printf("i = %d k3 = %d\n",i,k3[i]);
        }

        init();

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

}

int main()
{
    while( cin>>n )
    {
        for( int i = 0; i < n; ++i )
            sf("%d",&a[i]);
        for( int i = 0; i < n; ++ i )
            sf("%d",&b[i]);
    }

    solve();
}


#include <iostream>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <map>
#include <string.h>
#include <stdio.h>
#define sf scanf
#define pf printf
#define ll long long

#define clr(x) memset(x,0,sizeof(x))
#define _clr(x) memset(x,-1,sizeof(x))
#define fr(i,a,b) for(int i = a; i < b; ++i )

using namespace std;

int n;

int a[200020], b[200020];
int k1[200020], k2[200020], k3[200020];

ll c[200020];

void add( int t, int d )
{
    ++t;
    for( int i = t; i <=n; i += i & -i )
        c[i]+=d;
    //printf("add t = %d d = %d\n",t,d);
}

int sum( int t )
{
    ++t;
    int ret = 0;
    for( int i = t; i > 0; i -= i & -i )
        ret += c[i];
    //printf("find t = %d ret = %d\n",t,ret);
    return ret;
}

void init()
{
    clr( c );
    for( int i = 0; i <n; ++i )
        add( i, 1 );
}

void get( int * a, int * k )
{
    init();
    set< int > ft;
    for( int i = 0; i < n; ++i )
    {
        k[i] = sum(a[i]-1);
        add( a[i], -1 );
    }
}

set< int > nima;

int find( int k )
{
    int l = -1, r = n;
    while( l + 1 < r )
    {
        int mid = ( l + r ) >> 1;
        int index = sum( mid );
        //printf("mid = %d index = %d\n",mid, index );
        if( index > k ){
            r = mid;
        }
        else
            l = mid;
    }

//  printf("fid k = %d l = %d\n",k, l);

    add( l+1, -1 );
    return l+1;
}

int ans[200020];

void solve()
{
    clr( k1 );
    clr( k2 );
    clr( k3 );

        get( a, k1 );
        get ( b, k2 );

        for( int i = n-1; i >=0 ; --i )
        {
            k3[i] += k1[i] + k2[i] ;
            if( i > 0 ) k3[i-1] += k3[i] /(n-i);
            k3[i] %=(n-i);
            //printf("i = %d k3 = %d\n",i,k3[i]);
        }
/*
        int ix=0;
        for(int i=n-1;i>=0;i--)
        {
            k3[i]=(k1[i]+k2[i]+ix)%(n-i);
            ix=(k1[i]+k2[i]+ix)/(n-i);
        }
        */

        init();

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

}

int main()
{
    while( cin>>n )
    {
        for( int i = 0; i < n; ++i )
            sf("%d",&a[i]);
        for( int i = 0; i < n; ++ i )
            sf("%d",&b[i]);
    }

    solve();
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define INF 1000000007
#define N 100005
using namespace std;
int p[200005],q[200005];
int n;
int bitp[200005],bitq[200005];
int num[200005];
set<int> ss;
typedef set<int>::iterator rit;
int lowbit(int x)
{
    return x&(-x);
}
void ins(int x,int Bit[])
{
    while (x<=n)
    {
        Bit[x]++;
        x+=lowbit(x);
    }
}
int getsum(int x,int Bit[])
{
    int sum=0;
    while (x>0)
    {
        sum+=Bit[x];
        x-=lowbit(x);
    }
    return sum;
}
int lt[N],rt[N],key[N],sz[N];
int root=0,cnt=0;

void LeftRotate(int &x)
{
    int y=rt[x];
    rt[x]=lt[y];
    lt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void RightRotate(int &x)
{
    int y=lt[x];
    lt[x]=rt[y];
    rt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void Maintain(int &x,bool RightDeeper)
{
    if (!RightDeeper)
    {
        if (sz[lt[lt[x]]]>sz[rt[x]])
            RightRotate(x);
        else
        if (sz[rt[lt[x]]]>sz[rt[x]])
        {
            LeftRotate(lt[x]);
            RightRotate(x);
        }
        else
        return ;
    }
    else
    {
        if (sz[rt[rt[x]]]>sz[lt[x]])
            LeftRotate(x);
        else
        if (sz[lt[rt[x]]]>sz[lt[x]])
        {
            RightRotate(rt[x]);
            LeftRotate(x);
        }
        else
        return ;
    }
    Maintain(lt[x],0);
    Maintain(rt[x],1);
    Maintain(x,1);
    Maintain(x,0);
}
void Insert(int &x,int value)
{
    if (x==0)
    {
        cnt++;
        x=cnt;
        lt[x]=0;
        rt[x]=0;
        sz[x]=1;
        key[x]=value;
        return ;
    }
    sz[x]++;
    if (value<key[x])
        Insert(lt[x],value);
    else
        Insert(rt[x],value);
    Maintain(x,value>=key[x]);
}
int del(int &x,int value)
{
    sz[x]--;
    if (value==key[x]||(value<key[x]&&lt[x]==0)||(value>key[x]&&rt[x]==0))
    {
        int y=key[x];
        if (lt[x]==0||rt[x]==0)
            x=lt[x]+rt[x];
        else
            key[x]=del(lt[x],key[x]+1);
        return y;
    }
    else
    {
        if (value<key[x])
            return del(lt[x],value);
        else
            return del(rt[x],value);
    }
}
int Select(int &x,int r)
{
    int rank=sz[lt[x]]+1;
    if (rank==r)
        return key[x];
    else
    if (rank<r)
        return Select(rt[x],r-rank);
    else
        return Select(lt[x],r);
}
void puttree(int x)
{
    if (lt[x]!=0)
        puttree(lt[x]);
    printf("%d ",key[x]);
    if (rt[x]!=0)
        puttree(rt[x]);
}
int main(void)
{
    int i,j,k;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&p[i]);
        p[i]++;
    }
    for (i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
        q[i]++;
    }
    for (i=1;i<=n;i++)
    {
        j=n-i+1;
        num[j]+=getsum(p[j],bitp)+getsum(q[j],bitq);
    //    printf("%d\n",num[j]);
        num[j-1]+=num[j]/i;
        num[j]=num[j]%i;
        ins(p[j],bitp);
        ins(q[j],bitq);
    }
//    for (i=1;i<=n;i++)
//        printf("%d ",num[i]);
//    printf("\n");
    for (i=0;i<=n-1;i++)
        Insert(root,i);
    for (i=1;i<=n;i++)
    {
        p[i]=Select(root,num[i]+1);
        del(root,p[i]);
//        puttree(root);
//        printf("\n");
    }
    for (i=1;i<=n;i++)
        printf("%d ",p[i]);
    printf("\n");
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define INF 1000000007
#define N 200005
using namespace std;
int p[200005],q[200005];
int n;
int bitp[200005],bitq[200005];
int num[200005];
int lowbit(int x)
{
    return x&(-x);
}
void ins(int x,int Bit[])
{
    while (x<=n)
    {
        Bit[x]++;
        x+=lowbit(x);
    }
}
int getsum(int x,int Bit[])
{
    int sum=0;
    while (x>0)
    {
        sum+=Bit[x];
        x-=lowbit(x);
    }
    return sum;
}
int lt[N],rt[N],key[N],sz[N];
int root=0,cnt=0;

void LeftRotate(int &x)
{
    int y=rt[x];
    rt[x]=lt[y];
    lt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void RightRotate(int &x)
{
    int y=lt[x];
    lt[x]=rt[y];
    rt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void Maintain(int &x,bool RightDeeper)
{
    if (!RightDeeper)
    {
        if (sz[lt[lt[x]]]>sz[rt[x]])
            RightRotate(x);
        else
        if (sz[rt[lt[x]]]>sz[rt[x]])
        {
            LeftRotate(lt[x]);
            RightRotate(x);
        }
        else
        return ;
    }
    else
    {
        if (sz[rt[rt[x]]]>sz[lt[x]])
            LeftRotate(x);
        else
        if (sz[lt[rt[x]]]>sz[lt[x]])
        {
            RightRotate(rt[x]);
            LeftRotate(x);
        }
        else
        return ;
    }
    Maintain(lt[x],0);
    Maintain(rt[x],1);
    Maintain(x,1);
    Maintain(x,0);
}
void Insert(int &x,int value)
{
    if (x==0)
    {
        cnt++;
        x=cnt;
        lt[x]=0;
        rt[x]=0;
        sz[x]=1;
        key[x]=value;
        return ;
    }
    sz[x]++;
    if (value<key[x])
        Insert(lt[x],value);
    else
        Insert(rt[x],value);
    Maintain(x,value>=key[x]);
}
int del(int &x,int value)
{
    sz[x]--;
    if (value==key[x]||(value<key[x]&&lt[x]==0)||(value>key[x]&&rt[x]==0))
    {
        int y=key[x];
        if (lt[x]==0||rt[x]==0)
            x=lt[x]+rt[x];
        else
            key[x]=del(lt[x],key[x]+1);
        return y;
    }
    else
    {
        if (value<key[x])
            return del(lt[x],value);
        else
            return del(rt[x],value);
    }
}
int Select(int &x,int r)
{
    int rank=sz[lt[x]]+1;
    if (rank==r)
        return key[x];
    else
    if (rank<r)
        return Select(rt[x],r-rank);
    else
        return Select(lt[x],r);
}
void puttree(int x)
{
    if (lt[x]!=0)
        puttree(lt[x]);
    printf("%d ",key[x]);
    if (rt[x]!=0)
        puttree(rt[x]);
}
int main(void)
{
    int i,j,k;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&p[i]);
        p[i]++;
    }
    for (i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
        q[i]++;
    }
    for (i=1;i<=n;i++)
    {
        j=n-i+1;
        num[j]+=getsum(p[j],bitp)+getsum(q[j],bitq);
    //    printf("%d\n",num[j]);
        num[j-1]+=num[j]/i;
        num[j]=num[j]%i;
        ins(p[j],bitp);
        ins(q[j],bitq);
    }
//    for (i=1;i<=n;i++)
//        printf("%d ",num[i]);
//    printf("\n");
    for (i=0;i<=n-1;i++)
        Insert(root,i);
    for (i=1;i<=n;i++)
    {
        p[i]=Select(root,num[i]+1);
        del(root,p[i]);
//        puttree(root);
//        printf("\n");
    }
    for (i=1;i<=n;i++)
        printf("%d ",p[i]);
    printf("\n");
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int p[200005],q[200005];
int n;
int bitp[200005],bitq[200005];
int num[200005];
set<int> ss;
typedef set<int>::iterator rit;
int lowbit(int x)
{
    return x&(-x);
}
void ins(int x,int Bit[])
{
    while (x<=n)
    {
        Bit[x]++;
        x+=lowbit(x);
    }
}
int getsum(int x,int Bit[])
{
    int sum=0;
    while (x>0)
    {
        sum+=Bit[x];
        x-=lowbit(x);
    }
    return sum;
}
int main(void)
{
    int i,j,k;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&p[i]);
        p[i]++;
    }
    for (i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
        q[i]++;
    }
    for (i=1;i<=n;i++)
    {
        j=n-i+1;
        num[j]+=getsum(p[j],bitp)+getsum(q[j],bitq);
    //    printf("%d\n",num[j]);
        num[j-1]+=num[j]/i;
        num[j]=num[j]%i;
        ins(p[j],bitp);
        ins(q[j],bitq);
    }
//    for (i=1;i<=n;i++)
//        printf("%d ",num[i]);
//    printf("\n");
    for (i=0;i<=n-1;i++)
        ss.insert(i);
    for (i=1;i<=n;i++)
    {
        rit t;
        for (t=ss.begin(),j=0;j<num[i];j++)
            t++;
        p[i]=*t;
        ss.erase(t);
    }
    for (i=1;i<=n;i++)
        printf("%d ",p[i]);
    printf("\n");
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define INF 1000000007
#define N 100005
using namespace std;
int p[200005],q[200005];
int n;
int bitp[200005],bitq[200005];
int num[200005];
set<int> ss;
typedef set<int>::iterator rit;
int lowbit(int x)
{
    return x&(-x);
}
void ins(int x,int Bit[])
{
    while (x<=n)
    {
        Bit[x]++;
        x+=lowbit(x);
    }
}
int getsum(int x,int Bit[])
{
    int sum=0;
    while (x>0)
    {
        sum+=Bit[x];
        x-=lowbit(x);
    }
    return sum;
}
int lt[N],rt[N],key[N],sz[N];
int root=0,cnt=0;

void LeftRotate(int &x)
{
    int y=rt[x];
    rt[x]=lt[y];
    lt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void RightRotate(int &x)
{
    int y=lt[x];
    lt[x]=rt[y];
    rt[y]=x;
    sz[y]=sz[x];
    sz[x]=sz[lt[x]]+sz[rt[x]]+1;
    x=y;
}
void Maintain(int &x,bool RightDeeper)
{
    if (!RightDeeper)
    {
        if (sz[lt[lt[x]]]>sz[rt[x]])
            RightRotate(x);
        else
        if (sz[rt[lt[x]]]>sz[rt[x]])
        {
            LeftRotate(lt[x]);
            RightRotate(x);
        }
        else
        return ;
    }
    else
    {
        if (sz[rt[rt[x]]]>sz[lt[x]])
            LeftRotate(x);
        else
        if (sz[lt[rt[x]]]>sz[lt[x]])
        {
            RightRotate(rt[x]);
            LeftRotate(x);
        }
        else
        return ;
    }
    Maintain(lt[x],0);
    Maintain(rt[x],1);
    Maintain(x,1);
    Maintain(x,0);
}
void Insert(int &x,int value)
{
    if (x==0)
    {
        cnt++;
        x=cnt;
        lt[x]=0;
        rt[x]=0;
        sz[x]=1;
        key[x]=value;
        return ;
    }
    sz[x]++;
    if (value<key[x])
        Insert(lt[x],value);
    else
        Insert(rt[x],value);
    Maintain(x,value>=key[x]);
}
int del(int &x,int value)
{
    sz[x]--;
    if (value==key[x]||(value<key[x]&&lt[x]==0)||(value>key[x]&&rt[x]==0))
    {
        int y=key[x];
        if (lt[x]==0||rt[x]==0)
            x=lt[x]+rt[x];
        else
            key[x]=del(lt[x],key[x]+1);
        return y;
    }
    else
    {
        if (value<key[x])
            return del(lt[x],value);
        else
            return del(rt[x],value);
    }
}
int Select(int &x,int r)
{
    int rank=sz[lt[x]]+1;
    if (rank==r)
        return key[x];
    else
    if (rank<r)
        return Select(rt[x],r-rank);
    else
        return Select(lt[x],rank);
}
int main(void)
{
    int i,j,k;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&p[i]);
        p[i]++;
    }
    for (i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
        q[i]++;
    }
    for (i=1;i<=n;i++)
    {
        j=n-i+1;
        num[j]+=getsum(p[j],bitp)+getsum(q[j],bitq);
    //    printf("%d\n",num[j]);
        num[j-1]+=num[j]/i;
        num[j]=num[j]%i;
        ins(p[j],bitp);
        ins(q[j],bitq);
    }
//    for (i=1;i<=n;i++)
//        printf("%d ",num[i]);
//    printf("\n");
    for (i=0;i<=n-1;i++)
        Insert(root,i);
    for (i=1;i<=n;i++)
    {
        p[i]=Select(root,num[i]+1);
        del(root,p[i]);
    }
    for (i=1;i<=n;i++)
        printf("%d ",p[i]);
    printf("\n");
    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

long long factorials[200001];
long long toBeSummed1[200001], toBeSummed2[200001], sumResult[200001];

typedef struct
{
    int numLeaves;
    int val;
    int maxLeafVal;
} Node;

Node tree[400001];

int initTreeHelper(int leaves, int i)
{
    if(i >= leaves)
    {
        tree[i].numLeaves = 1;
        tree[i].maxLeafVal = tree[i].val;
        return tree[i].numLeaves;
    }
    else
    {
        tree[i].numLeaves = initTreeHelper(leaves, i << 1) +
                            initTreeHelper(leaves, (i << 1) + 1);
        tree[i].maxLeafVal = tree[(i << 1) + 1].maxLeafVal;
        return tree[i].numLeaves;
    }
}

int initTree(int n)
{
    int numNodes = (n << 1) - 1;
    int leftmostLeafIndex;
    for(int i=31; i >= 0; --i)
    {
        if((1 << i) & numNodes)
        {
            leftmostLeafIndex = (1 << i);
            break;
        }
    }

    for(int i = leftmostLeafIndex, j = 0; i <= numNodes; ++i, ++j)
    {
        tree[i].val = j;
    }

    for(int i = leftmostLeafIndex - 1, j = n-1; i >= n; --i, --j)
    {
        tree[i].val = j;
    }

    initTreeHelper(n, 1);
}

int findOrderOfKthLeaf(int k, int leaves, int i)
{
    if(i >= leaves)
    {
        return 0;
    }

    if(k > tree[i << 1].maxLeafVal)
    {
        return findOrderOfKthLeaf(k, leaves, (i << 1) + 1) + tree[i << 1].numLeaves;
    }
    else
    {
        return findOrderOfKthLeaf(k, leaves, i << 1);
    }
}

int getNthSmallest(int n, int leaves, int i)
{
    int result;
    if(i >= leaves)
    {
        tree[i].numLeaves--;
        return tree[i].val;
    }

    if(n < tree[i << 1].numLeaves)
    {
        result = getNthSmallest(n, leaves, i << 1);
    }
    else
    {
        result = getNthSmallest(n - tree[i << 1].numLeaves, leaves, (i << 1) + 1);
    }
    tree[i].numLeaves--;
    return result;
}

void translatePermutationOrder(int seq[], int n, int ind, long long res[])
{
    res[ind] = findOrderOfKthLeaf(seq[ind], n, 1);
    getNthSmallest(res[ind], n, 1);
    if(ind == n - 1)
        return;

    translatePermutationOrder(seq, n, ind + 1, res);
}

void sumR(long long n)
{
    int carry = 0;
    int mod = 2;
    for(int i=n-2; i >= 0; --i)
    {
        sumResult[i] = toBeSummed1[i] + toBeSummed2[i] + carry;
        if(sumResult[i] >= mod)
        {
            carry = sumResult[i] / mod;
            sumResult[i] %= mod;
        }
        else
            carry = 0;
        mod++;
    }
    sumResult[n-1] = 0;
}

void print(long long n)
{
    for(int i=0; i < n; ++i)
    {
        cout << getNthSmallest(sumResult[i], n, 1) << " ";
    }
}

int main()
{
    long long m, n, t;
    int P[200001], Q[200001];
    long long p = 0, q = 0;

    cin >> n;

    for(int i=0; i < n; ++i)
    {
        cin >> P[i];
    }
    for(int i=0; i < n; ++i)
    {
        cin >> Q[i];
    }

    initTree(n);
    translatePermutationOrder(P, n, 0, toBeSummed1);
    initTree(n);
    translatePermutationOrder(Q, n, 0, toBeSummed2);

    sumR(n);
    initTree(n);
    print(n);

    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

long long factorials[200001];
long long toBeSummed1[200001], toBeSummed2[200001], sumResult[200001];

void translatePermutationOrder(int seq[], int n, int ind, long long res[])
{
    res[ind] = seq[ind];
    if(ind == n - 1)
        return;
    for(int i=ind + 1; i < n; ++i)
    {
        if(seq[i] > seq[ind])
        {
            --seq[i];
        }
    }
    translatePermutationOrder(seq, n, ind + 1, res);
    return;
}

void sumR(long long n)
{
    int carry = 0;
    int mod = 2;
    for(int i=n-2; i >= 0; --i)
    {
        sumResult[i] = toBeSummed1[i] + toBeSummed2[i] + carry;
        if(sumResult[i] >= mod)
        {
            carry = sumResult[i] / mod;
            sumResult[i] %= mod;
        }
        else
            carry = 0;
        mod++;
    }
    sumResult[n-1] = 0;
}

map< int, int > stuff;

set<int> toBePrinted;
void print(long long n)
{
    set<int>::iterator it;
    for(int i=0; i < n; ++i)
    {
        it = toBePrinted.begin();
        advance(it, sumResult[i]);
        cout << *it << " ";
        toBePrinted.erase(it);
    }
}

int main()
{
    long long m, n, t;
    int P[200001], Q[200001];
    long long p = 0, q = 0;

    cin >> n;
    factorials[0] = 1;
    for(int i=1; i <= n; ++i)
    {
       factorials[i] = factorials[i-1] * i;
    }

    for(int i=0; i < n; ++i)
    {
        toBePrinted.insert(i);
        cin >> P[i];
    }
    for(int i=0; i < n; ++i)
    {
        cin >> Q[i];
    }

    translatePermutationOrder(P, n, 0, toBeSummed1);
    translatePermutationOrder(Q, n, 0, toBeSummed2);

    sumR(n);
    print(n);

    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

long long factorials[200001];
long long toBeSummed1[200001], toBeSummed2[200001], sumResult[200001];

void translatePermutationOrder(int seq[], int n, int ind, long long res[])
{
    res[ind] = seq[ind];
    if(ind == n - 1)
        return;
    for(int i=ind + 1; i < n; ++i)
    {
        if(seq[i] > seq[ind])
        {
            --seq[i];
        }
    }
    translatePermutationOrder(seq, n, ind + 1, res);
    return;
}

void sumR(long long n)
{
    int carry = 0;
    for(int i=n-2; i >= 0; --i)
    {
        sumResult[i] = toBeSummed1[i] + toBeSummed2[i] + carry;
        if(sumResult[i] >= n)
        {
            carry = sumResult[i] / n;
            sumResult[i] %= n;
        }
    }
    sumResult[n-1] = 0;
}

map< int, int > stuff;

set<int> toBePrinted;
void print(long long n)
{
    set<int>::iterator it;
    for(int i=0; i < n; ++i)
    {
        it = toBePrinted.begin();
        advance(it, sumResult[i]);
        cout << *it << " ";
        toBePrinted.erase(it);
    }
}

int main()
{
    long long m, n, t;
    int P[200001], Q[200001];
    long long p = 0, q = 0;

    cin >> n;
    factorials[0] = 1;
    for(int i=1; i <= n; ++i)
    {
       factorials[i] = factorials[i-1] * i;
    }

    for(int i=0; i < n; ++i)
    {
        toBePrinted.insert(i);
        cin >> P[i];
    }
    for(int i=0; i < n; ++i)
    {
        cin >> Q[i];
    }

    translatePermutationOrder(P, n, 0, toBeSummed1);
    translatePermutationOrder(Q, n, 0, toBeSummed2);

    sumR(n);
    print(n);

    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

long long factorials[200001];
long long toBeSummed1[200001], toBeSummed2[200001], sumResult[200001];

void translatePermutationOrder(int seq[], int n, int ind, long long res[])
{
    res[ind] = seq[ind];
    if(ind == n - 1)
        return;
    for(int i=ind + 1; i < n; ++i)
    {
        if(seq[i] > seq[ind])
        {
            --seq[i];
        }
    }
    translatePermutationOrder(seq, n, ind + 1, res);
    return;
}

void sumR(long long n)
{
    int carry = 0;
    int mod = 2;
    for(int i=n-2; i >= 0; --i)
    {
        sumResult[i] = toBeSummed1[i] + toBeSummed2[i] + carry;
        if(sumResult[i] >= mod)
        {
            carry = sumResult[i] / mod;
            sumResult[i] %= mod;
        }
        mod++;
    }
    sumResult[n-1] = 0;
}

map< int, int > stuff;

set<int> toBePrinted;
void print(long long n)
{
    set<int>::iterator it;
    for(int i=0; i < n; ++i)
    {
        it = toBePrinted.begin();
        advance(it, sumResult[i]);
        cout << *it << " ";
        toBePrinted.erase(it);
    }
}

int main()
{
    long long m, n, t;
    int P[200001], Q[200001];
    long long p = 0, q = 0;

    cin >> n;
    factorials[0] = 1;
    for(int i=1; i <= n; ++i)
    {
       factorials[i] = factorials[i-1] * i;
    }

    for(int i=0; i < n; ++i)
    {
        toBePrinted.insert(i);
        cin >> P[i];
    }
    for(int i=0; i < n; ++i)
    {
        cin >> Q[i];
    }

    translatePermutationOrder(P, n, 0, toBeSummed1);
    translatePermutationOrder(Q, n, 0, toBeSummed2);

    sumR(n);
    print(n);

    return 0;
}


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>

using namespace std;

long long factorials[200001];
long long toBeSummed1[200001], toBeSummed2[200001], sumResult[200001];

typedef struct
{
    int numLeaves;
    int val;
} Node;

Node tree[400001];

int initTree(int leaves, int i)
{
    if(i >= leaves)
    {
        tree[i].numLeaves = 1;
        return tree[i].numLeaves;
    }
    else
    {
        tree[i].numLeaves = initTree(leaves, i << 1) +
                            initTree(leaves, (i << 1) + 1);
        return tree[i].numLeaves;
    }
}

int getNthSmallest(int n, int leaves, int i)
{
    int result;
    if(i >= leaves)
    {
		tree[i].numLeaves--;
        return tree[i].val;
    }

	if(n < tree[i << 1].numLeaves)
	{
		result = getNthSmallest(n, leaves, i << 1);
	}
	else
	{
		result = getNthSmallest(n - tree[i << 1].numLeaves, leaves, (i << 1) + 1);
	}
    tree[i].numLeaves--;
	return result;
}

void translatePermutationOrder(int seq[], int n, int ind, long long res[])
{
    res[ind] = seq[ind];
    if(ind == n - 1)
        return;
    for(int i=ind + 1; i < n; ++i)
    {
        if(seq[i] > seq[ind])
        {
            --seq[i];
        }
    }
    translatePermutationOrder(seq, n, ind + 1, res);
    return;
}

void sumR(long long n)
{
    int carry = 0;
    int mod = 2;
    for(int i=n-2; i >= 0; --i)
    {
        sumResult[i] = toBeSummed1[i] + toBeSummed2[i] + carry;
        if(sumResult[i] >= mod)
        {
            carry = sumResult[i] / mod;
            sumResult[i] %= mod;
        }
        else
            carry = 0;
        mod++;
    }
    sumResult[n-1] = 0;
}

void print(long long n)
{
    for(int i=0; i < n; ++i)
    {
		cout << getNthSmallest(sumResult[i], n, 1) << " ";
    }
}

int main()
{
    long long m, n, t;
    int P[200001], Q[200001];
    long long p = 0, q = 0;

    cin >> n;
    int numNodes = (n << 1) - 1;
    int leftmostLeafIndex;
    for(int i=31; i >= 0; --i)
    {
        if((1 << i) & numNodes)
        {
            leftmostLeafIndex = (1 << i);
            break;
        }
    }

    for(int i = leftmostLeafIndex, j = 0; i <= numNodes; ++i, ++j)
    {
        tree[i].val = j;
    }

    for(int i = leftmostLeafIndex - 1, j = n-1; i >= n; --i, --j)
    {
        tree[i].val = j;
    }

    initTree(n, 1);
    for(int i=0; i < n; ++i)
    {
        cin >> P[i];
    }
    for(int i=0; i < n; ++i)
    {
        cin >> Q[i];
    }

    translatePermutationOrder(P, n, 0, toBeSummed1);
    translatePermutationOrder(Q, n, 0, toBeSummed2);

    sumR(n);
    print(n);

    return 0;
}


#include <iostream>
#include <string>
#include <string.h>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;
const int start = 48;
const int nsum = 97-start+26+5;
const int maxn = nsum*nsum;
const int maxm = 2e5+5;

int n;
int sum[maxn] , tmp[maxn];
int getsum(int i){
	int res = 0;
	while ( i>0 ){
		res += sum[i];
		i -= i&-i;
	}
	return res;
}
void add(int i,int ad){
	while ( i<=n ){
		sum[i] += ad;
		i += i&-i;
	}
}

int q[maxn],p[maxn],c[maxn];

int main(){
	//cout<< (int)('0') <<endl;
	while ( scanf("%d",&n)!=EOF ){
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++) add(i,1);
		for(int i=1;i<=n;i++) tmp[i] = sum[i];

		for(int i=1;i<=n;i++){
			int k; scanf("%d",&k); k++;
			p[i] = getsum(k)-1; add(k,-1);
		}

		for(int i=1;i<=n;i++) sum[i] = tmp[i];
		for(int i=1;i<=n;i++){
			int k; scanf("%d",&k); k++;
			q[i] = getsum(k)-1; add(k,-1);
		}

		memset(c,0,sizeof(c));
		for(int i=n;i>=1;i--){
			int k = n-i; c[i] += q[i]+p[i];
			if ( c[i]>=k+1 ){
				c[i-1]++; c[i] -= k+1;
			}
		}

		for(int i=1;i<=n;i++) sum[i] = tmp[i];
		for(int i=1;i<=n;i++){
			c[i]++;
			int l = 1 , r = n , mid ;
			while(l<r-1){
				mid = (l+r)>>1;
				if ( getsum(mid)<c[i] ) l = mid;
				else r = mid;
			}
			if ( getsum(l)==c[i] ) mid = l;
			else mid = r;
			c[i] = mid; add(mid,-1);
		}
		for(int i=1;i<=n;i++)
			printf("%d " , c[i]-1);
		printf("\n");
	}

	return 0;
}


#include <iostream>
#include <string>
#include <string.h>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;
const int start = 48;
const int maxn = 4e5+5;

int n;
int sum[maxn] , tmp[maxn];
int getsum(int i){
	int res = 0;
	while ( i>0 ){
		res += sum[i];
		i -= i&-i;
	}
	return res;
}
void add(int i,int ad){
	while ( i<=n ){
		sum[i] += ad;
		i += i&-i;
	}
}

int q[maxn],p[maxn],c[maxn];

int main(){
	//cout<< (int)('0') <<endl;
	while ( scanf("%d",&n)!=EOF ){
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++) add(i,1);
		for(int i=1;i<=n;i++) tmp[i] = sum[i];

		for(int i=1;i<=n;i++){
			int k; scanf("%d",&k); k++;
			p[i] = getsum(k)-1; add(k,-1);
		}

		for(int i=1;i<=n;i++) sum[i] = tmp[i];
		for(int i=1;i<=n;i++){
			int k; scanf("%d",&k); k++;
			q[i] = getsum(k)-1; add(k,-1);
		}

		memset(c,0,sizeof(c));
		for(int i=n;i>=1;i--){
			int k = n-i; c[i] += q[i]+p[i];
			if ( c[i]>=k+1 ){
				c[i-1]++; c[i] -= k+1;
			}
		}

		for(int i=1;i<=n;i++) sum[i] = tmp[i];
		for(int i=1;i<=n;i++){
			c[i]++;
			int l = 1 , r = n , mid ;
			while(l<r-1){
				mid = (l+r)>>1;
				if ( getsum(mid)<c[i] ) l = mid;
				else r = mid;
			}
			if ( getsum(l)==c[i] ) mid = l;
			else mid = r;
			c[i] = mid; add(mid,-1);
		}
		for(int i=1;i<=n;i++)
			printf("%d " , c[i]-1);
		printf("\n");
	}

	return 0;
}


#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

int n;
int arr[200001], a[200001], b[200001];
int fa[200001], fb[200001];
int a2[200001], b2[200001];

void add(int* t, int i, int value) {
    for(; i < n; i += (i + 1) & -(i + 1))
    t[i] += value;
}
int sum(int* t, int i) {
    int res = 0;
    for(; i >= 0; i -= (i + 1) & -(i + 1))
    res += t[i];
    return res;
}

int main(){
    scanf("%d", &n);

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

    memset(fa, 0, sizeof(fa));
    memset(fb, 0, sizeof(fb));

    for(int i=0; i<n; i++){
        if(i != 0){
            add(fa, i, 1);
            add(fb, i, 1);
        }
    }

    for(int i=0; i<n; i++){
        a2[i] = sum(fa, a[i]);
        add(fa, a[i], -1);
        b2[i] = sum(fb, b[i]);
        add(fb, b[i], -1);
    }

    int cnt = 2;
    for(int i=n-2; i>=0; i--){
        arr[i] += a2[i]+b2[i];
        if(arr[i] >= cnt && i > 0){
            arr[i-1]++;
        }
        arr[i] %= cnt;
        cnt++;
    }

    vector<int> list;
    for(int i=0; i<n; i++){
        list.push_back(i);
    }

    for(int i=0; i<n; i++){
        if(i != 0) printf(" ");
        printf("%d", list[arr[i]]);
        list.erase(list.begin()+arr[i]);
    }
    printf("\n");

    return 0;
}


#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

int n, n2;
int arr[200001], a[200001], b[200001];
int fa[200001], fb[200001];
int a2[200001], b2[200001];
int ft[200001];

void add(int* t, int i, int value) {
    for(; i < n; i += (i + 1) & -(i + 1))
    t[i] += value;
}
int sum(int* t, int i) {
    int res = 0;
    for(; i >= 0; i -= (i + 1) & -(i + 1))
    res += t[i];
    return res;
}

int lower_bound(int* t, int sum) {
    --sum; int pos = -1;
    for(int b = n2; b != 0; b >>= 1) {
    int nextPos = pos + b;
    if(nextPos < n && sum >= t[nextPos]) {
    sum -= t[nextPos];
    pos = nextPos; }}
    return pos + 1;
}

int main(){
    scanf("%d", &n);
    for(int i=31; i>=0; i--){
        if( (n&(1<<i)) != 0){
            n2 = (1 << i);
            break;
        }
    }

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

    memset(fa, 0, sizeof(fa));
    memset(fb, 0, sizeof(fb));

    for(int i=0; i<n; i++){
        if(i != 0){
            add(fa, i, 1);
            add(fb, i, 1);
        }
    }

    for(int i=0; i<n; i++){
        a2[i] = sum(fa, a[i]);
        add(fa, a[i], -1);
        b2[i] = sum(fb, b[i]);
        add(fb, b[i], -1);
    }

    int cnt = 2;
    for(int i=n-2; i>=0; i--){
        arr[i] += a2[i]+b2[i];
        if(arr[i] >= cnt && i > 0){
            arr[i-1]++;
        }
        arr[i] %= cnt;
        cnt++;
    }

    memset(ft, 0, sizeof(ft));
    for(int i=1; i<n; i++){
        add(ft, i, 1);
    }

    for(int i=0; i<n; i++){
        if(i != 0) printf(" ");
        int temp = lower_bound(ft, arr[i]);
        printf("%d", temp);
        add(ft, temp, -1);

        // printf("\n----\n");
        // for(int j=0; j<n; j++){
            // printf("%d ", sum(ft, j));
        // }
        // printf("\n----\n");
    }
    printf("\n");

    return 0;
}


#include <bits/stdc++.h>
#define ft first
#define sd second
#define mp make_pair
#define lowbit(x) ((x)&(-(x)))
using namespace std;

inline void cmin(int& x,int y){if (y<x) x=y;}
inline void cmax(int& x,int y){if (y>x) x=y;}

const int N=200000+5;

int n,f[N],a[N],b[N],c[N];

inline void add(int x)
{
	for (;x<=n;x+=lowbit(x)) ++f[x];
}

inline int getans(int x)
{
	int rt=0;
	for (;x>0;x-=lowbit(x)) rt+=f[x];
	return rt;
}

inline int calc(int x)
{
	int pos=0,rt=0;
	for (int k=17;~k;--k)
		if (pos+(1<<k)<=n && pos+(1<<k)-(rt+f[pos+(1<<k)])<x)
			rt+=f[pos+=1<<k];
	return pos+1;
}

int main()
{
	int x;
	scanf("%d",&n);
	memset(f,0,sizeof f);
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&x);
		a[i]=x-getans(x+1);
		add(x+1);
	}
	memset(f,0,sizeof f);
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&x);
		b[i]=x-getans(x+1);
		add(x+1);
	}
	for (int i=1;i<=n;++i) c[i]=a[i]+b[i];
	for (int i=n;i>=1;--i) c[i-1]+=c[i]/(n-i+1),c[i]%=n-i+1;
	memset(f,0,sizeof f);
	for (int i=1;i<=n;++i)
	{
		printf("%d%c",x=calc(c[i]+1)-1," \n"[i==n]);
		add(x+1);
	}
	return 0;
}


#include <iostream>
using namespace std;

int bit[200005], N;

int read(int k) {
    int sum = 0;
    while(k > 0) {
        sum += bit[k];
        k -= (k & -k);
    }
    return sum;
}

void update(int i, int v) {
    while(i <= N) {
        bit[i] += v;
        i += (i & -i);
    }
}

int a[200005], b[200005], s[200005];
int main() {
    ios_base::sync_with_stdio(false);
    cin >> N;
    for(int i = 0; i < N; i++) cin >> a[i];
    for(int i = 0; i < N; i++) cin >> b[i];
    for(int i = N-1; i >= 0; i--) {
        s[i] += read(a[i]+1);
        update(a[i]+1, 1);
    }
    for(int i = 0; i <= N; i++) bit[i] = 0;
    for(int i = N-1; i >= 0; i--) {
        s[i] += read(b[i]+1);
        update(b[i]+1, 1);
    }
    for(int i = N-1; i >= 1; i--) {
        int m = N - i;
        s[i-1] += s[i] / m;
        s[i] %= m;
    }   s[0] %= N;
    for(int i = 1; i <= N; i++) bit[i] = 0;
    for(int i = 1; i <= N; i++) update(i,1);
    for(int i = 0; i < N; i++) {
        int goal = s[i]+1;
        int l = 1, h = N, m;
        while(h-l > 1) {
            m = (l + h) / 2;
            //cout << endl << "--- " << goal << " " << l << " " << m << " " << h << endl;
            if(read(m) < goal) l = m;
            else h = m;
        }
        if(read(l) == goal) m = l;
        else m = h;
        //cout << ">> " << l << " " << m << " " << h << " " << read(l) << " " << read(m) << " " << read(h) << endl;
        update(m, -1);
        cout << m-1; if(i < N-1) cout << " ";
    }   cout << endl;
    //for(int i = 0; i < N; i++) cout << s[i] << " ";
    //cout << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define err(x) cout<<#x<<"= "<<x<<endl;
#define FOR(i,a,b) for(int i =a; i< b; ++i)
#define rep(i,n) FOR(i,0,n)
#define pb push_back
#define INF 1000000000
#define TRVI(it,it1,it2) for(vi::iterator it = it1; it!= it2; it++)
#define ff first
#define ss second
#define mp make_pair
#define pq priority_queue<int, vector<int>, greater<int> >
#define ll long long
const ll PR = 1000000009;
#define SIZE 1
#define vi vector<int>
#define pii pair<int,int>

class SegmentTree{
//	typedef int int;                        // int is the struct st stores.
	vector<int> st;
	int n;
	inline int left(int p){return p<<1;}
	inline int right(int p){return (p<<1) +1;}

	int combine(int a, int b){                           // data combine(data a, data b) an assosiative operation which acts on data
		return a+b;
	}

	void build(int p, int l, int r){
		if(l==r){
			st[p] = 1;
			return;
		}
		int mid = l+r>>1;
		build(left(p), l, mid);
		build(right(p), mid+1, r);
		st[p] = combine(st[left(p)] , st[right(p)]);
	}

	int query(int p, int l, int r, int ql, int qr){           // int query(...)
		if(r<ql || l>qr){
			return 0;                                           // Return a null value, which doesnt affect combine ie.combine(a,null)= a
		}
		if(l>= ql && r<= qr){
			return st[p];
		}
		int mid= l+r >>1;
		int p1 = query(left(p), l, mid, ql, qr), p2 = query(right(p), mid+1,r,ql, qr);
		return combine(p1,p2);
	}
	public:
	SegmentTree(int n1){
		this->n = n1;
		st.assign(4*n1,0);
		build(1,0,n1-1);
	}
//	~SegmentTree(){
//		cout<<"destroyed"<<endl;
//	}
	int query(int a, int b){                   // a to b inclusive
		return query(1, 0,n-1, a,b);
	}
	void adjust(int a, int b, int val){
		int p = 1,l=0, r= n-1;
		for( ; ;){
			st[p]+= val;
			if(l==r)break;
			int mid= l+r>>1;
			if(mid< a){
				p = right(p); l =mid+1;
			}
			else{
				p = left(p); r= mid;
			}
		}
	}
	int find(int presum){
		int p = 1,l= 0, r=n-1;
		int mid= l+r>>1;
		int sum = 0;
		while(l!=r){
			mid = l+r>>1;
			if(presum-sum > st[left(p)]){
				sum+= st[left(p)];
				p = right(p);
				l = mid+1;
			}
			else{
				p = left(p);
				r = mid;
			}
		}
		return l;
	}
};
int n;
vector<int> p, q,r,p1,q1;

void findord(){
	SegmentTree tr(p.size()),tr2(p.size());
	for(int i=0;i< n; i++){
		tr.adjust(p[i],p[i], -1);

		p1.pb(tr.query(0, p[i]));
	}
	for(int i=0; i< n; i++){
		tr2.adjust(q[i],q[i], -1);
		q1.pb(tr2.query(0, q[i]));
	}
}
void sum(){
	int cr = 0;//r.assign(n,0);
	for(int i = n-1; i>=0; i--){
		p1.pb(i);q1.pb(i);
		r[i]+= cr+p1[i] + q1[i];
		cr=0;
		while(r[i] > n-i-1){
			r[i]-= n-i;cr++;
		}
	}
}

int main(){
	ios::sync_with_stdio(false);

	cin>>n;
	r.assign(n,0);
	for(int i=0;i< n; i++){
		int a;
		cin>>a;
		p.pb(a);
	}
	for(int i =0; i<n; i++){
		int b;
		cin>>b;
		q.pb(b);
	}

	findord();

	sum();
	SegmentTree tr1(n);

//	SegmentTree tr1(n);
//	cout<<"okay"<<endl;
//	cout<<"OKAY"<<endl;
	for(int i =0; i< n; i++){
	//	cout<<r[i]<<' ';
				int pos = tr1.find(r[i]+1);
				cout<<pos<<' ';//<<i<<endl;
				tr1.adjust(pos,pos,-1);
	}
	cout<<endl;
	return 0;
};


#include<bits/stdc++.h>
using namespace std;
#define err(x) cout<<#x<<"= "<<x<<endl;
#define FOR(i,a,b) for(int i =a; i< b; ++i)
#define rep(i,n) FOR(i,0,n)
#define pb push_back
#define INF 1000000000
#define TRVI(it,it1,it2) for(vi::iterator it = it1; it!= it2; it++)
#define ff first
#define ss second
#define mp make_pair
#define pq priority_queue<int, vector<int>, greater<int> >
#define ll long long
const ll PR = 1000000009;
#define SIZE 1
#define vi vector<int>
#define pii pair<int,int>

class SegmentTree{
	typedef int data;                        // data is the struct st stores.
	vector<data> st;
	int n;
	inline int left(int p){return p<<1;}
	inline int right(int p){return (p<<1) +1;}

	data combine(data a, data b){                           // data combine(data a, data b) an assosiative operation which acts on data
		return a+b;
	}

	void build(int p, int l, int r){
		if(l==r){
			st[p] = 1;
			return;
		}
		int mid = l+r>>1;
		build(left(p), l, mid);
		build(right(p), mid+1, r);
		st[p] = combine(st[left(p)] , st[right(p)]);
	}

	data query(int p, int l, int r, int ql, int qr){           // data query(...)
//		cout<< l<<' '<<r<<' ' <<ql<<' '<<qr<<endl;
		if(r<ql || l>qr){
			return 0;                                           // Return a null value, which doesnt affect combine ie.combine(a,null)= a
		}
		if(l>= ql && r<= qr){
			return st[p];
		}
		int mid= l+r >>1;
		data p1 = query(left(p), l, mid, ql, qr), p2 = query(right(p), mid+1,r,ql, qr);
		return combine(p1,p2);
	}
/*	int find(int p, int l, int r, int psum){
		if(l==r)return l;
		int mid = query(l, l+r>>1);
		if(mid>=psum)
			return find(left(p), l,l+r>>1, psum);
		else
			return find(right(p), (l+r>>1)+1, r,psum - mid);
	}*/

	public:
	SegmentTree(int _n){
		n = _n;
		st.assign(2*n+5, data());
		build(1,0,n-1);
	}
	int query(int a, int b){                   // a to b inclusive
		return query(1, 0,n-1, a,b);
	}
	void adjust(int a, int b, data val){
		int p = 1,l=0, r= n-1;
		for( ; ;){
			st[p]+= val;
			if(l==r)break;
			int mid= l+r>>1;
			if(mid< a){
				p = right(p); l =mid+1;
			}
			else{
				p = left(p); r= mid;
			}
		}
	}
	int find(int presum){
		int p = 1,l= 0, r=n-1;
		int mid= l+r>>1;
		int sum = 0;
		while(l!=r){
			mid = l+r>>1;
			if(presum-sum > st[left(p)]){
				sum+= st[left(p)];
				p = right(p);
				l = mid+1;
			}
			else{
				p = left(p);
				r = mid;
			}
		}
		return l;
//		return find(1,0,n-1, presum);
	}
};
int n;
vector<int> p, q,r,p1,q1;

void findord(){
	SegmentTree tr(p.size()),tr2(p.size());
//	cout<<"ennachi"<<endl;
	for(int i=0;i< n; i++){
		tr.adjust(p[i],p[i], -1);

		p1.pb(tr.query(0, p[i]));
	}
	for(int i=0; i< n; i++){
		tr2.adjust(q[i],q[i], -1);
		q1.pb(tr2.query(0, q[i]));
	}
//	cout<<"prachanalla"<<endl;
}
void sum(){
	int cr = 0;r.assign(n,0);
	for(int i = n-1; i>=0; i--){
		r[i]+= cr+p1[i] + q1[i];
		cr=0;
		while(r[i] > n-i-1){
			r[i]-= n-i;cr++;
		}
	}
}

int main(){
	ios::sync_with_stdio(false);

	cin>>n;
	for(int i=0;i< n; i++){
		int a;
		cin>>a;
		p.pb(a);
	}
	for(int i =0; i<n; i++){
		int b;
		cin>>b;
		q.pb(b);
	}
	findord();
	sum();
	SegmentTree tr(n);
	for(int i =0; i< n; i++){
		int pos = tr.find(r[i]+1);
		cout<<pos<<' ';
		tr.adjust(pos,pos,-1);
	}
	cout<<endl;

	return 0;
};


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            Array.Sort(ways, new Cmp());
            int a = ways[0].Item1, b = ways[0].Item2;
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                if (Find(u, ref p) == Find(a, ref r) && Find(v, ref p) == Find(b, ref p) ||
                    Find(u, ref p) == Find(b, ref r) && Find(u, ref p) == Find(a, ref p))
                {
                    Console.WriteLine(ways[i].Item3);
                    Environment.Exit(0);
                }
                else
                {
                    Unite(u, v, ref p, ref r);
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<(int a, int b, int e)>
        {
            public int Compare((int a, int b, int e) a, (int a, int b, int e) b)
            {
                if (a.e > b.e)
                    return 1;
                if (a.e < b.e)
                    return -1;
                return 0;
            }
        }

        private static (int a, int b, int e)[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new (int, int, int)[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = (temp[0] - 1, temp[1] - 1, temp[2]);
            }

            return ways;
        }

        private static void Kruskal(int m, ref (int a, int b, int e)[] ways, ref int[] p, ref int[] r)
        {
            Array.Sort(ways, new Cmp());
            var last = 0;
            for (var i = 0; i < m; i++)
            {
                int a = ways[i].a, b = ways[i].b;
                if (Find(a, ref p) != Find(b, ref r))
                {
                    Unite(a, b, ref p, ref r);
                    last = ways[i].e;
                }
                else
                {
                    Console.WriteLine(last);
                    Environment.Exit(0);
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p);
            Kruskal(m, ref ways, ref p);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p)
        {
            int a = ways[0].Item1, b = ways[0].Item2;
            ways[0] = new Tuple<int, int, int>(a, b, int.MinValue);
            Array.Sort(ways, new Cmp());
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                Unite(u, v, ref p);
                if (Find(a, ref p) == Find(b, ref p))
                {
                    Console.WriteLine(ways[i].Item3);
                    Environment.Exit(0);
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p)
        {
            p = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p)
        {
            var a = Find(u, ref p);
            var b = Find(v, ref p);
            if (u != v)
            {
                p[a] = b;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO.Enumeration;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            int a = ways[0].Item1, b = ways[0].Item2;
            ways[0] = new Tuple<int, int, int>(a, b, int.MinValue);
            Array.Sort(ways, new Cmp());
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                if (Find(u, ref p) != Find(v, ref p)) {
                    Unite(u, v, ref p, ref r);
                    if (Find(a, ref p) == Find(b, ref p))
                    {
                        Console.WriteLine(ways[i].Item3);
                        Environment.Exit(0);
                    }
                }

            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            int a = ways[0].Item1, b = ways[0].Item2;
            ways[0] = new Tuple<int, int, int>(a, b, int.MinValue);
            Array.Sort(ways, new Cmp());
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                if (Find(u, ref p) != Find(v, ref p)) {
                    Unite(u, v, ref p, ref r);
                    if (Find(a, ref p) == Find(b, ref p))
                    {
                        Console.WriteLine(ways[i].Item3);
                        Environment.Exit(0);
                    }
                }

            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            int a = ways[0].Item1, b = ways[0].Item2;
            ways[0] = new Tuple<int, int, int>(a, b, int.MinValue);
            Array.Sort(ways, new Cmp());
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                Unite(u, v, ref p, ref r);
                if (Find(a, ref p) == Find(b, ref p))
                {
                    Console.WriteLine(ways[i].Item3);
                    Environment.Exit(0);
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int a, int b, ref int[] p, ref int[] r)
        {
            var u = Find(a, ref p);
            var v = Find(b, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                {
                    int k = u;
                    u = v;
                    v = k;
                }
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            Array.Sort(ways, new Cmp());
            var last = 0;
            for (var i = 0; i < m; i++)
            {
                int a = ways[i].Item1, b = ways[i].Item2;
                if (Find(a, ref p) != Find(b, ref r))
                {
                    Unite(a, b, ref p, ref r);
                    last = ways[i].Item3;
                }
                else
                {
                    Console.WriteLine(last);
                    Environment.Exit(0);
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal static class Program
    {
        private static void Main(string[] args)
        {
            var ways = Reader(out var n, out var m);
            Init(n, out var p, out var r);
            Kruskal(m, ref ways, ref p, ref r);
        }

        private class Cmp: IComparer<Tuple<int, int, int>>
        {
            public int Compare(Tuple<int, int, int> a, Tuple<int, int, int> b)
            {
                if (a.Item3 > b.Item3)
                    return 1;
                if (a.Item3 < b.Item3)
                    return -1;
                return 0;
            }
        }

        private static Tuple<int, int, int>[] Reader(out int n, out int m)
        {
            var nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
            n = nm[0];
            m = nm[1];

            var ways = new Tuple<int, int, int>[m];
            for (var i = 0; i < m; i++)
            {
                var temp = Console.ReadLine().Split().Select(int.Parse).ToArray();
                ways[i] = new Tuple<int, int, int>(temp[0] - 1, temp[1] - 1, temp[2]);
            }
            return ways;
        }

        private static void Kruskal(int m, ref Tuple<int, int, int>[] ways, ref int[] p, ref int[] r)
        {
            int a = ways[0].Item1, b = ways[0].Item2;
            ways[0] = new Tuple<int, int, int>(a, b, int.MinValue);
            Array.Sort(ways, new Cmp());
            for (var i = 1; i < m; i++)
            {
                int u = ways[i].Item1, v = ways[i].Item2;
                if (Find(u, ref p) != Find(v, ref p))
                {
                    Unite(u, v, ref p, ref r);
                    if (Find(a, ref p) == Find(b, ref p))
                    {
                        Console.WriteLine(ways[i].Item3);
                        Environment.Exit(0);
                    }
                }
            }
            Console.WriteLine(1e9);
        }

        private static void Init(int n, out int[] p, out int[] r)
        {
            p = new int[n];
            r = new int[n];
            for (var i = 0; i < n; i++)
            {
                p[i] = i;
                r[i] = 0;
            }
        }

        private static int Find(int v, ref int[] p)
        {
            return v == p[v] ? v : p[v] = Find(p[v], ref p);
        }

        private static void Unite(int u, int v, ref int[] p, ref int[] r)
        {
            u = Find(u, ref p);
            v = Find(v, ref p);
            if (u != v)
            {
                if (r[u] < r[v])
                    (u, v) = (v, u);
                p[v] = u;
                if (r[u] == r[v])
                    r[u]++;
            }
        }
    }
}


from __future__ import division, print_function
def main():
    n,m=map(int,input().split())
    a,b,e=map(int,input().split())
    l1=[]
    flag1=0
    flag2=0
    for i in range(m-1):
        x,y,z=map(int,input().split())
        if x==a or y==a:
            flag1=1
            l1.append((z,x,y))
        elif y==b or x==b:
            flag2=1
            l1.append((z,x,y))

    l1.sort()
    if len(l1)==0 or flag1==0 or flag2==0:
        print(10**9)
    else :
        if l1[0][1]==a or l1[0][2]==a:
            i=0
            while l1[i][2]!=b and l1[i][1]!=b:
                i+=1
            print (l1[i][0])
        else :
            i=0
            while l1[i][1]!=a and l1[i][2]!=a:
                i+=1
            print(l1[i][0])

######## Python 2 and 3 footer by Pajenegod and c1729

# Note because cf runs old PyPy3 version which doesn't have the sped up
# unicode strings, PyPy3 strings will many times be slower than pypy2.
# There is a way to get around this by using binary strings in PyPy3
# but its syntax is different which makes it kind of a mess to use.

# So on cf, use PyPy2 for best string performance.

py2 = round(0.5)
if py2:
    from future_builtins import ascii, filter, hex, map, oct, zip
    range = xrange

import os, sys
from io import IOBase, BytesIO

BUFSIZE = 8192
class FastIO(BytesIO):
    newlines = 0

    def __init__(self, file):
        self._file = file
        self._fd = file.fileno()
        self.writable = "x" in file.mode or "w" in file.mode
        self.write = super(FastIO, self).write if self.writable else None

    def _fill(self):
        s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
        self.seek((self.tell(), self.seek(0,2), super(FastIO, self).write(s))[0])
        return s

    def read(self):
        while self._fill(): pass
        return super(FastIO,self).read()

    def readline(self):
        while self.newlines == 0:
            s = self._fill(); self.newlines = s.count(b"\n") + (not s)
        self.newlines -= 1
        return super(FastIO, self).readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.getvalue())
            self.truncate(0), self.seek(0)

class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        if py2:
            self.write = self.buffer.write
            self.read = self.buffer.read
            self.readline = self.buffer.readline
        else:
            self.write = lambda s:self.buffer.write(s.encode('ascii'))
            self.read = lambda:self.buffer.read().decode('ascii')
            self.readline = lambda:self.buffer.readline().decode('ascii')

sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip('\r\n')

# Cout implemented in Python
import sys
class ostream:
    def __lshift__(self,a):
        sys.stdout.write(str(a))
        return self
cout = ostream()
endl = '\n'

# Read all remaining integers in stdin, type is given by optional argument, this is fast
def readnumbers(zero = 0):
    conv = ord if py2 else lambda x:x
    A = []; numb = zero; sign = 1; i = 0; s = sys.stdin.buffer.read()
    try:
        while True:
            if s[i] >= b'0' [0]:
                numb = 10 * numb + conv(s[i]) - 48
            elif s[i] == b'-' [0]: sign = -1
            elif s[i] != b'\r' [0]:
                A.append(sign*numb)
                numb = zero; sign = 1
            i += 1
    except:pass
    if s and s[-1] >= b'0' [0]:
        A.append(sign*numb)
    return A

if __name__== "__main__":
  main()


from __future__ import division, print_function
def main():
    class DSU:
        def __init__ (self,n):
            self.parent=list(range(n))
            self.size=[1]*n
            self.count_sets=n
        def find(self,u):
            to_update=[]
            while u!=self.parent[u]:
                to_update.append(u)
                u=self.parent[u]
            for v in to_update:
                self.parent[v]=u
            return u
        def union(self,u,v):
            u=self.find(u)
            v=self.find(v)
            if u==v:
                return
            if self.size[u] < self.size[v]:
                u,v=v,u
            self.count_sets-=1
            self.parent[v]=u
            self.size[u]+=self.size[v]

        def set_size(self,a):
            return self.size[self.find(a)]
    n,m=map(int,input().split())
    a,b,e=map(int,input().split())
    a-=1
    b-=1
    l1=[]
    flag1=0
    flag2=0
    for i in range(m-1):
        x,y,z=map(int,input().split())
        l1.append((z,x-1,y-1))
    l1.sort()
    import sys
    my_dsu=DSU(n)
    for item in l1:
        if my_dsu.find(item[1])!=my_dsu.find(item[2]):
            my_dsu.union(item[1],item[2])
        if my_dsu.find(a)==my_dsu.find(b):
            print(item[0])
            sys.exit()
    print(10**9)

######## Python 2 and 3 footer by Pajenegod and c1729

# Note because cf runs old PyPy3 version which doesn't have the sped up
# unicode strings, PyPy3 strings will many times be slower than pypy2.
# There is a way to get around this by using binary strings in PyPy3
# but its syntax is different which makes it kind of a mess to use.

# So on cf, use PyPy2 for best string performance.

py2 = round(0.5)
if py2:
    from future_builtins import ascii, filter, hex, map, oct, zip
    range = xrange

import os, sys
from io import IOBase, BytesIO

BUFSIZE = 8192
class FastIO(BytesIO):
    newlines = 0

    def __init__(self, file):
        self._file = file
        self._fd = file.fileno()
        self.writable = "x" in file.mode or "w" in file.mode
        self.write = super(FastIO, self).write if self.writable else None

    def _fill(self):
        s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
        self.seek((self.tell(), self.seek(0,2), super(FastIO, self).write(s))[0])
        return s

    def read(self):
        while self._fill(): pass
        return super(FastIO,self).read()

    def readline(self):
        while self.newlines == 0:
            s = self._fill(); self.newlines = s.count(b"\n") + (not s)
        self.newlines -= 1
        return super(FastIO, self).readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.getvalue())
            self.truncate(0), self.seek(0)

class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        if py2:
            self.write = self.buffer.write
            self.read = self.buffer.read
            self.readline = self.buffer.readline
        else:
            self.write = lambda s:self.buffer.write(s.encode('ascii'))
            self.read = lambda:self.buffer.read().decode('ascii')
            self.readline = lambda:self.buffer.readline().decode('ascii')

sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip('\r\n')

# Cout implemented in Python
import sys
class ostream:
    def __lshift__(self,a):
        sys.stdout.write(str(a))
        return self
cout = ostream()
endl = '\n'

# Read all remaining integers in stdin, type is given by optional argument, this is fast
def readnumbers(zero = 0):
    conv = ord if py2 else lambda x:x
    A = []; numb = zero; sign = 1; i = 0; s = sys.stdin.buffer.read()
    try:
        while True:
            if s[i] >= b'0' [0]:
                numb = 10 * numb + conv(s[i]) - 48
            elif s[i] == b'-' [0]: sign = -1
            elif s[i] != b'\r' [0]:
                A.append(sign*numb)
                numb = zero; sign = 1
            i += 1
    except:pass
    if s and s[-1] >= b'0' [0]:
        A.append(sign*numb)
    return A

if __name__== "__main__":
  main()


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Andy Phan
 */
public class e1 {

    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        int m = in.nextInt();

        int fA = in.nextInt();
        int fB = in.nextInt();
        int cost = in.nextInt();

        PriorityQueue<Edge> q = new PriorityQueue<Edge>((Edge a, Edge b) -> a.e-b.e);

        q.add(new Edge(fA, fB, cost));
        for(int i = 1; i < m; i++) q.add(new Edge(in.nextInt(), in.nextInt(), in.nextInt()));

        DisjointSet a = new DisjointSet(n+1);
        DisjointSet b = new DisjointSet(n+1);

        a.union(fA, fB);

        long costA = cost, costB = 0;

        while(!q.isEmpty()) {
            Edge curr = q.poll();
            if(a.union(curr.u, curr.v)) costA += curr.e;
            if(b.union(curr.u, curr.v)) costB += curr.e;
        }

        System.out.println(cost+costB-costA);

        out.close();
    }

    static class Edge {
        int u, v, e;

        public Edge(int U, int V, int E) {
            u = U;
            v = V;
            e = E;
        }
    }

    static class DisjointSet {

        int[] s;

        public DisjointSet(int n) {
            Arrays.fill(s = new int[n], -1);
        }

        public int find(int i) {
            return s[i] < 0 ? i : (s[i] = find(s[i]));
        }

        public boolean union(int a, int b) {
            if ((a = find(a)) == (b = find(b))) {
                return false;
            }
            if (s[a] == s[b]) {
                s[a]--;
            }
            if (s[a] <= s[b]) {
                s[b] = a;
            } else {
                s[a] = b;
            }
            return true;
        }
    }

    static class FS {

        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if (token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Andy Phan
 */
public class e1 {

    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        int m = in.nextInt();

        int fA = in.nextInt();
        int fB = in.nextInt();
        int cost = in.nextInt();

        PriorityQueue<Edge> q = new PriorityQueue<Edge>((Edge a, Edge b) -> a.e-b.e);

        q.add(new Edge(fA, fB, cost));
        for(int i = 1; i < m; i++) q.add(new Edge(in.nextInt(), in.nextInt(), in.nextInt()));

        DisjointSet a = new DisjointSet(n+1);
        DisjointSet b = new DisjointSet(n+1);

        a.union(fA, fB);

        long costA = 0, costB = 0;

        while(!q.isEmpty()) {
            Edge curr = q.poll();
            if(a.union(curr.u, curr.v)) costA += curr.e;
            if(b.union(curr.u, curr.v)) costB += curr.e;
        }

        System.out.println(costB-costA);

        out.close();
    }

    static class Edge {
        int u, v, e;

        public Edge(int U, int V, int E) {
            u = U;
            v = V;
            e = E;
        }
    }

    static class DisjointSet {

        int[] s;

        public DisjointSet(int n) {
            Arrays.fill(s = new int[n], -1);
        }

        public int find(int i) {
            return s[i] < 0 ? i : (s[i] = find(s[i]));
        }

        public boolean union(int a, int b) {
            if ((a = find(a)) == (b = find(b))) {
                return false;
            }
            if (s[a] == s[b]) {
                s[a]--;
            }
            if (s[a] <= s[b]) {
                s[b] = a;
            } else {
                s[a] = b;
            }
            return true;
        }
    }

    static class FS {

        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if (token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Andy Phan
 */
public class e1 {

    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        int m = in.nextInt();

        int fA = in.nextInt();
        int fB = in.nextInt();
        int cost = in.nextInt();

        PriorityQueue<Edge> q = new PriorityQueue<Edge>((Edge a, Edge b) -> a.e-b.e);

        q.add(new Edge(fA, fB, cost));
        for(int i = 1; i < m; i++) q.add(new Edge(in.nextInt(), in.nextInt(), in.nextInt()));

        DisjointSet a = new DisjointSet(n+1);
        DisjointSet b = new DisjointSet(n+1);

        a.union(fA, fB);

        long costA = 0, costB = 0;

        while(!q.isEmpty()) {
            Edge curr = q.poll();
            if(a.union(curr.u, curr.v)) costA += curr.e;
            if(curr.u != fA && curr.v != fB && b.union(curr.u, curr.v)) costB += curr.e;
        }
        for(int i = 1; i <= n; i++) if(b.union(1, i)) costB = 1000000000+costA;
        System.out.println(costB-costA);

        out.close();
    }

    static class Edge {
        int u, v, e;

        public Edge(int U, int V, int E) {
            u = U;
            v = V;
            e = E;
        }
    }

    static class DisjointSet {

        int[] s;

        public DisjointSet(int n) {
            Arrays.fill(s = new int[n], -1);
        }

        public int find(int i) {
            return s[i] < 0 ? i : (s[i] = find(s[i]));
        }

        public boolean union(int a, int b) {
            if ((a = find(a)) == (b = find(b))) {
                return false;
            }
            if (s[a] == s[b]) {
                s[a]--;
            }
            if (s[a] <= s[b]) {
                s[b] = a;
            } else {
                s[a] = b;
            }
            return true;
        }
    }

    static class FS {

        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if (token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Andy Phan
 */
public class e1 {

    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        int m = in.nextInt();

        int fA = in.nextInt();
        int fB = in.nextInt();
        int cost = in.nextInt();

        PriorityQueue<Edge> q = new PriorityQueue<Edge>((Edge a, Edge b) -> a.e-b.e);

        q.add(new Edge(fA, fB, cost));
        for(int i = 1; i < m; i++) q.add(new Edge(in.nextInt(), in.nextInt(), in.nextInt()));

        DisjointSet a = new DisjointSet(n+1);
        DisjointSet b = new DisjointSet(n+1);

        a.union(fA, fB);

        long costA = 0, costB = 0;

        while(!q.isEmpty()) {
            Edge curr = q.poll();
            if(a.union(curr.u, curr.v)) costA += curr.e;
            if((curr.u != fA || curr.v != fB) && b.union(curr.u, curr.v)) costB += curr.e;
        }
        for(int i = 1; i <= n; i++) if(b.union(1, i)) costB = 1000000000+costA;
        System.out.println(costB-costA);

        out.close();
    }

    static class Edge {
        int u, v, e;

        public Edge(int U, int V, int E) {
            u = U;
            v = V;
            e = E;
        }
    }

    static class DisjointSet {

        int[] s;

        public DisjointSet(int n) {
            Arrays.fill(s = new int[n], -1);
        }

        public int find(int i) {
            return s[i] < 0 ? i : (s[i] = find(s[i]));
        }

        public boolean union(int a, int b) {
            if ((a = find(a)) == (b = find(b))) {
                return false;
            }
            if (s[a] == s[b]) {
                s[a]--;
            }
            if (s[a] <= s[b]) {
                s[b] = a;
            } else {
                s[a] = b;
            }
            return true;
        }
    }

    static class FS {

        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if (token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.util.*;
import java.io.*;
import java.text.*;

public class E1_1184 {

	static Edge[] edgeList;
	static int V;

	static long kruskal() {
		long mst = 0;
		UnionFind uf = new UnionFind(V);
		uf.union(edgeList[0].u, edgeList[0].v);
		mst += edgeList[0].w;
		Arrays.sort(edgeList);

		for (Edge e : edgeList)
			if (uf.union(e.u, e.v))
				mst += e.w;
		return mst;
	}
	static long kruskal(Edge firstEdge) {
		long mst = 0;
		UnionFind uf = new UnionFind(V);

		Arrays.sort(edgeList);

		for (Edge e : edgeList)
			if (e!=firstEdge && uf.union(e.u, e.v))
				mst += e.w;
		return uf.size==1? mst:-1;
	}
	static class Edge implements Comparable<Edge> {
		int u, v, w;

		Edge(int a, int b, int c) {
			u = a;
			v = b;
			w = c;
		}

		public int compareTo(Edge e) {
			return w - e.w;
		}
	}

	static class UnionFind {
		int[] p, rank;
		int size;

		UnionFind(int N) {
			p = new int[N];
			size=N;
			rank = new int[N];
			for (int i = 0; i < N; i++)
				p[i] = i;
		}

		int findSet(int x) {
			return p[x] == x ? x : (p[x] = findSet(p[x]));
		}

		boolean union(int x, int y) {
			x = findSet(x);
			y = findSet(y);
			if (x == y)
				return false;

			size--;
			if (rank[x] > rank[y])
				p[y] = x;
			else {
				p[x] = y;
				if (rank[x] == rank[y])
					++rank[y];
			}
			return true;
		}
	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		V = sc.nextInt();
		int m = sc.nextInt();
		edgeList = new Edge[m];
		for (int i = 0; i < m; i++) {
			int x = sc.nextInt() - 1;
			int y = sc.nextInt() - 1;
			int w = sc.nextInt();
			Edge e = new Edge(x, y, w);
			edgeList[i] = e;
		}
		Edge firstEdge = edgeList[0];
		long mst = kruskal();
		long mst2 = kruskal(firstEdge);
		if(mst2==-1)
			pw.println((int)1e9);
		else
		{
			long dif = mst - mst2;
			long ans =Math.min( Math.max(firstEdge.w-dif,0),(int)1e9);
			pw.println(ans);
		}
		pw.flush();
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

	}

}