import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

/*

単調増加列 単調増加部分列 座標圧縮
区分木 セグメント木 セグメントツリー SegTree Segment Tree
二分探索

----------------------------------------

「花 i までの中から作った単調増加列について、最大の花の高さが h 以下であるときの美しさの最大値」
を x[i][h] とする

これは、iをとめたとき、hに関して単調増加(あたりまえ)

x[i][h] は、
h < h[i] のとき　x[i - 1][h]
h >= h[i] のとき
	x[i - 1][h[i] - 1] + a[i] と x[i - 1][h] の良い方

----------------------------------------

上記はTLEになるので何とかする

x[h]は、
「花 i までの中から作った単調増加列について、最大の花の高さが h 以下であるときの美しさの最大値」
である
これはhに関して単調増加である

初めは、全てのhに対して x[h] = 0
iを動かしながら、x[h]を次のルールに従って更新していく

x' = x[h[i] - 1] + a[i] とおく。これはi番目の花を採用する場合の美しさの最大値である

h < h[i] である範囲のhに対しては現状維持
h[i] <= h かつ x[h] < x' である範囲のhに対して、x[h] = x'
x' < x[h] である範囲のhに対しては現状維持

ここで x[h] < x' なる最大のhを求めるところは二分探索でいける

範囲への書き込みは、x[h]を区分木で持つことにすればいける

この区分木は、「範囲への書き込み」「1点の読み出し(二分探索で)」をサポートすればよい
（※二分探索自体の機能も区分木のほうにつければもっと高速になるのかもしれないが必要ない）

今回の区分木のNodeは以下の機能を持てばよい
・区間への書き込み
	区間が全体の場合→自分が値を持つ。自分の値を与えられた値とする。終わり。
	区間が全体ではない場合→もし自分が値を持っていれば、まず自分の値を子たちに持たせる。その後、子たちに書き込む。
・１点の読み出し
	自分が値を持っていれば、その値を返す。
	持っていなければ、該当する子に移譲する。

*/

// 区分木(区間への書き込み、1点の読み出し)
class SegTree{
	long value;
	SegTree left, right; // 左の子(a <= x < c)、右の子(c <= x < b)
	bool hasValue;
	bool isTerminal;
	SegTree parent;
	int a, b; // a <= x < b を担当する
	this(int a, int b){
		this.a = a, this.b = b;
		if(b - a == 1){
			this.isTerminal = 1;
		}
		else{
			int c = (a + b) / 2;
			this.left = new SegTree(a, c);
			this.right = new SegTree(c, b);
		}
	}
	
	// [a, b) に値を設定する ※[a, b) はこのノードの担当区間とかぶっていなくてもよい
	void setValue(int a, int b, long value){
		if(b <= this.a || this.b <= a) return;
		if(a <= this.a && this.b <= b){
			this.hasValue = 1;
			this.value = value;
		}
		else{
			if(this.hasValue){
				this.hasValue = 0;
				this.left.hasValue = 1, this.left.value = this.value;
				this.right.hasValue = 1, this.right.value = this.value;
			}
			this.left.setValue(a, b, value);
			this.right.setValue(a, b, value);
		}
	}
	
	// iにおける値 ※iは必ずこのノードの担当区間内である前提
	long getValue(int i){
		if(this.hasValue) return this.value;
		if(i < left.b) return left.getValue(i);
		else return right.getValue(i);
	}
	
	long[] array(){
		if(this.hasValue){
			long[] res;
			foreach(i; a .. b) res ~= this.value;
			return res;
		}
		else return this.left.array ~ this.right.array;
	}
	
	override string toString(){
		return this.array.to!string;
	}
}

// a <= x <=  c の中でfをみたす最大(二分探索; binary search) ※テンプレート版
T uplimit(T)(T a, T c, bool delegate(T) f){
	if(f(c)) return c;
	if(! f(a)) return a - 1;
	while(a + 1 < c){
		T b = (a + c) / 2;
		if(f(b)) a = b;
		else c = b;
	}
	return a;
}


void main(){
 int n = read.to!int;
 
 int[] hs = readln.chomp.split.map!(to!int).array;
 long[] as = readln.chomp.split.map!(to!long).array;
 
 SegTree seg = new SegTree(0, n + 1);
 
 seg.setValue(0, n + 1, 0);
 
 foreach(i; 0 .. n){
	 long x1 = seg.getValue(hs[i] - 1) + as[i];
	 int h1 = uplimit(0, n, (int h) => (seg.getValue(h) <= x1));
	 seg.setValue(hs[i], h1 + 1, x1);
	 debug writeln("i:", i, " hs[i]:", hs[i], " h1:", h1, " x1:", x1, " seg:", seg);
 }
	
	seg.getValue(n).writeln;
 
}
