Problem:
Score : 100 points

Problem Statement

There are N flowers arranged in a row.
For each i (1 \leq i \leq N), the height and the beauty of the i-th flower from the left is h_i and a_i, respectively.
Here, h_1, h_2, \ldots, h_N are all distinct.

Taro is pulling out some flowers so that the following condition is met:

The heights of the remaining flowers are monotonically increasing from left to right.

Find the maximum possible sum of the beauties of the remaining flowers.

Constraints

All values in input are integers.

1 \leq N \leq 2 × 10^5

1 \leq h_i \leq N

h_1, h_2, \ldots, h_N are all distinct.

1 \leq a_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
h_1 h_2 \ldots h_N
a_1 a_2 \ldots a_N

Output

Print the maximum possible sum of the beauties of the remaining flowers.

Sample Input 1

4
3 1 4 2
10 20 30 40

Sample Output 1

60

We should keep the second and fourth flowers from the left.
Then, the heights would be 1, 2 from left to right, which is monotonically increasing, and the sum of the beauties would be 20 + 40 = 60.

Sample Input 2

1
1
10

Sample Output 2

10

The condition is met already at the beginning.

Sample Input 3

5
1 2 3 4 5
1000000000 1000000000 1000000000 1000000000 1000000000

Sample Output 3

5000000000

The answer may not fit into a 32-bit integer type.

Sample Input 4

9
4 2 5 8 3 6 1 7 9
6 8 8 4 6 3 5 7 5

Sample Output 4

31

We should keep the second, third, sixth, eighth and ninth flowers from the left.

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#pragma GCC optimize("Ofast")
#define _USE_MATH_DEFINES
#include "bits/stdc++.h"

using namespace std;

using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i8 = int8_t;
using i32 = int32_t;
using i64 = int64_t;
constexpr char newl = '\n';

template<typename T1, typename T2> inline void chmin(T1& a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define F0R(i,b) FOR(i,0,b)
#define RFO(i,a,b) for (int i = ((b)-1); i >=(a); i--)
#define RF0(i,b) RFO(i,0,b)
//#define F first
//#define S second
#define debug(x) cout << #x << ": " << x << '\n';

#if 1

template<class T>
class SegmentTree {
public:
  SegmentTree(int size) {
    int n = 1;
    while (n < size) n <<= 1;

    int segCount = n * 2 - 1;

    maxes = vector<T>(segCount, 0);
    left = vector<int>(segCount);
    right = vector<int>(segCount);
    mp = vector<int>(segCount);
    childs = vector<pair<int, int>>(segCount);

    for (int i = 0, l = 0, w = n; i < segCount; i++) {
      left[i] = l;
      right[i] = left[i] + w;
      mp[i] = left[i] + (w >> 1);
      childs[i] = { ((i + 1) << 1) - 1, ((i + 1) << 1) };
      if (right[i] >= n) {
        w >>= 1; l = 0;
      }
      else {
        l += w;
      }
    }
  }

  void SetValue(T value, int index, int segIndex = 0) {

    if (left[segIndex] == index && index + 1 == right[segIndex]) {
      maxes[segIndex] = value;
      while (segIndex) {
        segIndex = ((segIndex + 1) >> 1) - 1; // parent
        if (maxes[segIndex] >= value) break;
        maxes[segIndex] = value;
      }
    }
    else {
      if (index < mp[segIndex]) {
        SetValue(value, index, childs[segIndex].first);
      }
      else {
        SetValue(value, index, childs[segIndex].second);
      }
    }
  }

  // [L, R)
  T GetMax(int pLeft, int pRight, int segIndex = 0) {

    //cout << "GetMax(" << pLeft << ", " << pRight << ", " << segIndex << ")" << newl;

    if (left[segIndex] == pLeft && right[segIndex] == pRight) {
      //debug(segIndex);
      //debug(maxes[segIndex]);
      return maxes[segIndex];
    }
    else {
      T result;
      if (pLeft < mp[segIndex]) {
        result = GetMax(pLeft, min(pRight, mp[segIndex]), childs[segIndex].first);
      }
      if (mp[segIndex] < pRight) {
        result = max(result, GetMax(max(pLeft, mp[segIndex]), pRight, childs[segIndex].second));
      }
      return maxes[segIndex] = result;
    }
  }

protected:

  vector<T> maxes;

  // 区間 [l, r) とその中間
  vector<int> left, right, mp;
  vector<pair<int, int>> childs;
  int power;
};

// INSERT ABOVE HERE
signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N;
  cin >> N;

  // dp[i][j] := i 番目までの花のうち、高さ j までを選んだときの最高スコア
  // dp[i][j]を計算するのに必要なのはdp[i-1][j-n]なので、dp[j]の1列だけ持てばいい

  // dp[i] := 現在処理している花までのうち、高さ i 以下の花を選んだときの最高スコア
  // 結果: TLE

  // これだと高さ h のスコアが更新されたときの処理時間が最悪 O(N) なので遅い。少し変える

  // dp[i] := 現在処理している花までのうち、高さ i 以下かつ高さ i の花を含んだ集合での最高スコア
  // 結果: TLE

  // これで更新自体の処理はO(1)になったが、高さ h 以下の最高スコアを得るのに最悪 O(N) かかってしまう
  // 一つ前の方法の方がTLEの数が少なかった

  // (ここで解説を読む)

  // 上記問題をSegment Treeが解決してくれるらしい


  vector<int> h(N), a(N);
  F0R(i, N) {
    cin >> h[i];
  }
  F0R(i, N) {
    cin >> a[i];
  }

  SegmentTree<i64> st(N+1);

  F0R(i, N) {
    i64 score = 0;
    score = st.GetMax(0, h[i]);
    //debug(score);

    score += a[i];
    st.SetValue(score, h[i]);
  }

  i64 result = st.GetMax(0, N + 1);
  cout << result;
}
#endif