#include<bits/stdc++.h>
using namespace std ;

// MY TOOLS
#define let long long int
#define async ios_base::sync_with_stdio(false);cin.tie(NULL);
#define i_upto( n ) for( int i = 0 ; i < n ; i++ )
#define ij_upto( n, m ) for( int i = 0 ; i < n ; i++ ) for( int j = 0 ; j < m ; j++ )
template<class T>
T ** array2D( let R , let C ){
	T ** t = new T * [R] ;
	for( int i = 0 ; i < R ; i++ ){
		t[i] = new T[C] ;
	}
	return t ;
}
template<class T>
T ** array2D( let R , let C, T value ){
	T ** t = new T * [R] ;
	for( int i = 0 ; i < R ; i++ ){
		t[i] = new T[C] ;
	}
    ij_upto( R, C ) t[i][j] = value ;
	return t ;
}
template<class T>
T * array1D( let N, T value ){
    T * t = new T[N] ;
    i_upto(N) t[i] = value ;
    return t ;
}
template<class T>
T * array1D( let N ){
    T * t = new T[N] ;
    return t ;
}
template<class T>
vector<vector<T>> vector2D( let N, let M ){
	return vector<vector<T>>(N,vector<T>(M)) ;
}
template<class T>
vector<vector<T>> vector2D( let N, let M, T Value ){
	return vector<vector<T>>(N,vector<T>(M,Value)) ;
}
#define then ;
#define vector2D( t ) vector<vector<t>>
template<class T>
class matrix{
	T ** v ;
	let rows, cols ;
	public :
		matrix( let n, let m ){
			v = array2D<T>( n, m ) ;
			rows = n ;
			cols = m ;
		}
		void input(){
			ij_upto( rows, cols ) cin >> v[i][j] ;
		}
		T& at( let i, let j ){
			return v[i][j] ;
		}
		T* at( let i ){
			return v[i] ;
		}
		void set( let i, let j, T value ){
			v[i][j] = value ;
		}
		void output(){
			for( let i = 0 ; i < rows ; i++ ){
				for( let j = 0 ; j < cols ; j++ ){
					cout << v[i][j] << " " ;
				}
				cout << endl ;
			}
		}
		void fill( T value ){
			ij_upto( rows, cols ) v[i][j] = value ;
		}
		T ** begin(){
			return v ;
		}
		T ** end(){
			return v + rows ;
		}
};

let Pow( let x, let n ){                             // runs in log n complexity
    if( n == 0 ) return 1 ;
    if( n & 1 ){
        return x * Pow( x*x, n/2 ) ;
    }
    return Pow( x*x,  n/2 ) ;
}
//
class SegmentedTree{                          // our tree
    public :
        let * st ;          // main segmented tree
        let * arr ;                 // array from which segmented tree is to be constructed
        let size ;      // size of the array
        let st_size ;                // total size of the array representation of the segmented tree
    SegmentedTree( let * Arr, let n ){
        arr = new let[n] ;
        for( int i = 0 ; i < n ; i++ ) arr[i] = Arr[i] ;        // copying data
        let temp = int( ceil(log2(n)) ) ;
        let st_size = 2*(int(Pow(2,temp))) - 1 ;
        st = new let [ st_size ] ;
        size = n ;
    }
    let getMid( let s, let e ){
        return s + ( e - s ) / 2 ;     // i have not used (e+s)/2 to prevent overflow in extreme cases
    }
    let buildUtil( let ss, let se, let cp ){
        if( ss == se )return st[cp] = arr[ss] ;      // base case
        return st[cp] = max( buildUtil( ss, getMid( ss, se ) , 2*cp+1), buildUtil( getMid( ss, se )+1, se, 2*cp+2) ) ;
    }
    void build(){
        buildUtil( 0, st_size-1, 0 ) ;
    }
    bool outside( let qs, let qe, let ss, let se ){
        if( qs > se || qe < ss ) return true ;
        return false ;
    }
    bool totallyInside( let qs, let qe, let ss, let se ){
        if( ss >= qs && se <= qe ) return true ;
        return false ;
    }
    let getMaxUtil( let qs, let qe, let ss, let se , let cp ){
        if( outside(qs, qe, ss, se) ) return 0 ;
        if( totallyInside(qs, qe, ss, se) ){
            return st[cp] ;
        }
        let mid = getMid( ss, se ) ;
        return max( getMaxUtil( qs, qe, ss, mid, 2*cp+1), getMaxUtil(qs, qe, mid+1, se, 2*cp+2) ) ; 
    }
    let getMax( let qs, let qe ){
        return getMaxUtil( qs, qe, 0, size-1, 0 ) ;
    }
    void updateUtil( let new_value, let pos, let ss, let se, let cp ){
        if( pos > se || pos < ss ) return ;
        if( ss == se ){
            st[cp] = new_value ;
            arr[pos] = new_value ;
            return ;
        }
        let mid = getMid( ss, se ) ;
        if( pos <= mid ) updateUtil( new_value, pos, ss, mid,2*cp+1 ) ;
        else updateUtil( new_value, pos, mid+1,se, 2*cp+2) ;
        st[cp] = max( st[2*cp+1], st[2*cp+2] ) ;
        return ;
    }
    void update( let index, let new_value ){
        updateUtil( new_value, index, 0, size-1, 0 ) ;
    }
};
// 0 -> height, 1 -> value, 2 -> orignal_index 
// main
// write your code here
int main(){
	async ;
	let N then cin >> N ;
	matrix<let> flowers( N, 3 ) ;
	for( int i = 0 ; i < N ; i++ ) cin >> flowers.at( i, 0 ) ;
	for( int i = 0 ; i < N ; i++ ) {
		cin >> flowers.at( i, 1 ) ;
		flowers.at( i, 2 ) = i ;
	}
	sort( flowers.begin(), flowers.end(),
	 			[]( let * a , let * b ) {
					 return a[0] < b[0] ; 
				 } 
		) ;
	let * arr = new let[N] ;
	for( int i = 0 ; i < N ; i++ ) arr[i] = 0 ;
	SegmentedTree dp( arr, N ) ;
	for( int i = 0 ; i < N ; i++ ){
		auto pick = flowers.at( i ) ;
		let value = pick[1] ;
		let index = pick[2] ;
		let max_value_before_me = dp.getMax(0, index-1) ;
		dp.update( index, max_value_before_me + value ) ;
	}
	cout << dp.getMax( 0, N-1 ) ;
    return 0 ;
}

Measured memory_bytes: 18692