#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 ;
		}
};
//
class segmented_tree{
public :
    let * st ;
    let * arr ;
    let size ;
    segmented_tree( let arr[] , let n ){
        size = n ;
        let temp = int( ceil(log2(n)) ) ;
        let max_size = 2*int(pow(2,temp)) - 1 ;
        st = new let[ max_size ] ;
        this -> arr = new let[n] ;
        for( let i = 0 ; i < n ; i++ ) (this -> arr)[i] = arr[i] ;
        construct_ST_util( arr , n , 0 , n-1 , 0 , st ) ;
    }
    let get_mid( let s , let e ){
        return s + ( e-s ) / 2 ;
    }
    let construct_ST_util( let arr[], let n, let cs, let ce, let cp, let * st ){
        // base case
        if( cs == ce ) {
            st[ cp ] = arr[ cs ] ;      // here cs is same as ce
            return st[ cp ] ;          // here st[ cp ] is same as arr[ cs ]
        }
        let mid = get_mid( cs , ce ) ;  // to divide the interval into two parts and then recuring them
        st[ cp ] = max( construct_ST_util( arr , n , cs , mid , 2*cp+1 , st ) ,
                   construct_ST_util( arr, n , mid+1, ce , 2*cp+2, st ) );
        return st[ cp ] ;
    }
    let get_max_util( let qs , let qe ,  let cs , let ce , let cp ){
        if( cs >= qs && ce <= qe ){
            return st[ cp ] ;
        }
        if( cs > qe || ce < qs ){
            return 0 ;
        }
        let mid = get_mid( cs , ce ) ;
        return max( get_max_util( qs , qe , cs , mid , 2*cp + 1 ) , get_max_util( qs , qe , mid+1 , ce , 2*cp + 2 ) ) ;
    }
    let max_val( let qs , let qe ){
        return get_max_util( qs , qe , 0 , size-1 , 0 ) ;
    }
    void update_util( let new_value , let pos , let cs , let ce , let cp ){
        if( pos < cs || pos > ce ) return ;
		if( cs == ce ){
			arr[pos] = new_value ;
			st[cp] = new_value ;
		}
		else{
			int mid = get_mid( cs, ce ) ;
			if( pos >= cs && pos <= mid ){
				update_util( new_value, pos, cs, mid, 2*cp + 1 ) ;
			}
			else{
				update_util( new_value, pos, mid+1, ce, 2*cp+2) ;
			}
			st[cp] = max(st[2*cp+1], st[2*cp+2]) ;
		}
		// if( cs == ce && cs != pos ) return st[cp] ;
        // if( cs == ce && cs == pos ){
        //     st[ cp ] = new_value ;
        //     return st[ cp ] ;
        // }
        // let mid = get_mid( cs , ce ) ;
        // st[ cp ] = max( update_util( new_value , pos , cs , mid , 2*cp + 1 ) ,update_util( new_value , pos , mid+1 , ce , 2*cp + 2 ) );
        // return st[ cp ] ;
    }
    void update( let pos , let new_value ){
        arr[ pos ] = new_value ;
        update_util( new_value , pos , 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[N] ;
	for( int i = 0 ; i < N ; i++ ) arr[i] = 0 ;
	segmented_tree 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.max_val(0, index-1) ;
		dp.update( index, max_value_before_me + value ) ;
	}
	cout << dp.max_val( 0, N-1 ) ;
    return 0 ;
}

Measured memory_bytes: 19204