#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N;
ll A[500005], B[500005];
ll prefB[500005]; // prefB[i] = B[1]+...+B[i], prefB[0]=0
bool check(ll x) {
// ---- Build vt1 (valid starting points j) ----
// Sweeping i from N down to 1.
// For monster i in the suffix phase (fighting j..N):
// strength when reaching i = x + prefB[i-1] - prefB[j-1]
// need: x + prefB[i-1] - prefB[j-1] >= A[i]
// => prefB[j-1] <= x + prefB[i-1] - A[i] (threshold)
//
// j ranges 1..i, so j-1 ranges 0..i-1.
// upper_bound(prefB, prefB+i, threshold) = first element > threshold in prefB[0..i-1]
// cnt = that offset = number of valid j-1 values (0..cnt-1)
// so maxJ(i) = cnt (valid j values are 1..cnt)
//
// Track runMin = min(maxJ) over i..N seen so far.
// When runMin == i: i is a valid starting point. Add to vt1, reset runMin.
vector<int> vt1;
vt1.reserve(N);
int runMin = INT_MAX;
for (int i = N; i >= 1; i--) {
ll threshold = x + prefB[i-1] - A[i];
// prefB[0..i-1] has i elements
int cnt = (int)(upper_bound(prefB, prefB + i, threshold) - prefB);
int maxJ = cnt; // largest j with prefB[j-1] <= threshold, j in [1..i]
runMin = min(runMin, maxJ);
if (runMin == i) {
vt1.push_back(i);
runMin = INT_MAX; // reset: next segment starts fresh
}
}
reverse(vt1.begin(), vt1.end()); // sorted ascending
if (vt1.empty()) return false;
// j=1 means no prefix needed, suffix 1..N covers everything
if (vt1[0] == 1) return true;
// ---- Build vt2 (valid prefix ending indices i) ----
// Sweeping i from 1 to N-1.
// For monster i in the prefix phase (fighting 1..j-1 after suffix j..N):
// strength when reaching i = x + prefB[N] - prefB[j-1] + prefB[i-1]
// need: >= A[i]
// => prefB[j-1] <= x + prefB[N] + prefB[i-1] - A[i] (threshold)
//
// j ranges 2..N, so j-1 ranges 1..N-1.
// upper_bound(prefB+1, prefB+N, threshold) = first element > threshold in prefB[1..N-1]
// cnt = offset from prefB+1 = number of valid j-1 values in [1..N-1]
// valid j = 2..cnt+1, so maxJ = min(cnt+1, N)
//
// Find largest element in vt1 <= maxJ (bestJ).
// Track currMin = min(bestJ) seen so far.
// Push i to vt2 while i < currMin. Stop when i >= currMin.
vector<int> vt2;
vt2.reserve(N);
int currMin = INT_MAX;
for (int i = 1; i <= N - 1; i++) {
ll threshold = x + prefB[N] + prefB[i-1] - A[i];
// prefB[1..N-1] has N-1 elements
int cnt = (int)(upper_bound(prefB + 1, prefB + N, threshold) - (prefB + 1));
int maxJ = min(cnt + 1, N); // j in [2..cnt+1], cap at N
// largest element in vt1 that is <= maxJ
auto it = upper_bound(vt1.begin(), vt1.end(), maxJ);
if (it == vt1.begin()) break; // no valid j in vt1 for this i
--it;
int bestJ = *it;
currMin = min(currMin, bestJ);
if (i < currMin) {
vt2.push_back(i);
} else {
break;
}
}
if (vt2.empty()) return false;
// ---- Final check: any i in vt2 with i+1 in vt1? ----
for (int i : vt2) {
if (binary_search(vt1.begin(), vt1.end(), i + 1)) {
return true;
}
}
return false;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N;
for (int i = 1; i <= N; i++) cin >> A[i];
for (int i = 1; i <= N; i++) cin >> B[i];
prefB[0] = 0;
for (int i = 1; i <= N; i++) prefB[i] = prefB[i-1] + B[i];
ll lo = 0, hi = 1e9;
while (lo < hi) {
ll mid = lo + (hi - lo) / 2;
if (check(mid)) hi = mid;
else lo = mid + 1;
}
cout << lo << "\n";
return 0;
}