/**
* created : 12.10.2024 20:25:04
* author : wzj33300
*/
#include <bits/stdc++.h>
using namespace std;
#ifdef DEBUG
#include <algo/debug.h>
#else
#define debug(...) 42
#define assert(...) 42
#endif
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using db = long double; // or double, if TL is tight
using str = string; // yay python!
// pairs
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;
#define mp make_pair
#define fi first
#define se second
// ^ lol this makes everything look weird but I'll try it
template <class T>
using vc = vector<T>;
template <class T, size_t SZ>
using AR = array<T, SZ>;
using vi = vc<int>;
using vb = vc<bool>;
using vl = vc<ll>;
using vd = vc<db>;
using vs = vc<str>;
using vpi = vc<pi>;
using vpl = vc<pl>;
using vpd = vc<pd>;
// vectors
// oops size(x), rbegin(x), rend(x) need C++17
#define sz(x) int((x).size())
#define bg(x) begin(x)
#define all(x) bg(x), end(x)
#define rall(x) x.rbegin(), x.rend()
#define sor(x) sort(all(x))
#define rsz resize
#define ins insert
#define pb push_back
#define eb emplace_back
#define ft front()
#define bk back()
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i < (n); ++i)
#define rep1n(i, n) for (int i = 1; i <= (n); ++i)
#define repr(i, n) for (int i = (n) - 1; i >= 0; --i)
#define rep_subset(t, s) \
for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#define lb lower_bound
#define ub upper_bound
template <class T>
int lwb(vc<T>& a, const T& b) {
return int(lb(all(a), b) - bg(a));
}
template <class T>
int upb(vc<T>& a, const T& b) {
return int(ub(all(a), b) - bg(a));
}
// const int MOD = 998244353; // 1e9+7;
const int Big = 1e9; // not too close to INT_MAX
const ll BIG = 1e18; // not too close to LLONG_MAX
const db PI = acos((db)-1);
const int dx[4]{1, 0, -1, 0}, dy[4]{0, 1, 0, -1}; // for every grid problem!!
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;
int pct(int x) { return __builtin_popcount(x); }
int pct(u32 x) { return __builtin_popcount(x); }
int pct(ll x) { return __builtin_popcountll(x); }
int pct(u64 x) { return __builtin_popcountll(x); }
int popcnt_mod_2(int x) { return __builtin_parity(x); }
int popcnt_mod_2(u32 x) { return __builtin_parity(x); }
int popcnt_mod_2(ll x) { return __builtin_parityll(x); }
int popcnt_mod_2(u64 x) { return __builtin_parityll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
template <typename T>
T floor(T a, T b) {
return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
T q = floor(x, y);
return {q, x - q * y};
}
template <class T>
bool ckmin(T& a, const T& b) {
return b < a ? a = b, 1 : 0;
} // set a = min(a,b)
template <class T>
bool ckmax(T& a, const T& b) {
return a < b ? a = b, 1 : 0;
} // set a = max(a,b)
template <class T, class U>
T fstTrue(T lo, T hi, U f) {
++hi;
assert(lo <= hi); // assuming f is increasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo) / 2;
f(mid) ? hi = mid : lo = mid + 1;
}
return lo;
}
template <class T, class U>
T lstTrue(T lo, T hi, U f) {
--lo;
assert(lo <= hi); // assuming f is decreasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo + 1) / 2;
f(mid) ? lo = mid : hi = mid - 1;
}
return lo;
}
namespace seg_tree {
// Floor of log_2(a); index of highest 1-bit
inline int floor_log_2(int a) {
return a ? bit_width(unsigned(a)) - 1 : -1;
}
struct point {
int a;
point() : a(0) {}
explicit point(int a_) : a(a_) { assert(a >= -1); }
explicit operator bool() { return bool(a); }
// This is useful so you can directly do array indices
/* implicit */ operator int() const { return a; }
point c(bool z) const {
return point((a << 1) | z);
}
point operator[](bool z) const {
return c(z);
}
point p() const {
return point(a >> 1);
}
friend std::ostream& operator<<(std::ostream& o, const point& p) { return o << int(p); }
template <typename F>
void for_each(F f) const {
for (int v = a; v > 0; v >>= 1) {
f(point(v));
}
}
template <typename F>
void for_parents_down(F f) const {
// strictly greater than 0
for (int L = floor_log_2(a); L > 0; L--) {
f(point(a >> L));
}
}
template <typename F>
void for_parents_up(F f) const {
for (int v = a >> 1; v > 0; v >>= 1) {
f(point(v));
}
}
point& operator++() {
++a;
return *this;
}
point operator++(int) { return point(a++); }
point& operator--() {
--a;
return *this;
}
point operator--(int) { return point(a--); }
};
struct range {
int a, b;
range() : a(1), b(1) {}
range(int a_, int b_) : a(a_), b(b_) {
assert(1 <= a && a <= b && b <= 2 * a);
}
explicit range(std::array<int, 2> r) : range(r[0], r[1]) {}
explicit operator std::array<int, 2>() const {
return {a, b};
}
const int& operator[](bool z) const {
return z ? b : a;
}
friend std::ostream& operator<<(std::ostream& o, const range& r) { return o << "[" << r.a << ".." << r.b << ")"; }
// Iterate over the range from outside-in.
// Calls f(point a)
template <typename F>
void for_each(F f) const {
for (int x = a, y = b; x < y; x >>= 1, y >>= 1) {
if (x & 1) f(point(x++));
if (y & 1) f(point(--y));
}
}
// Iterate over the range from outside-in.
// Calls f(point a, bool is_right)
template <typename F>
void for_each_with_side(F f) const {
for (int x = a, y = b; x < y; x >>= 1, y >>= 1) {
if (x & 1) f(point(x++), false);
if (y & 1) f(point(--y), true);
}
}
// Iterate over the range from left to right.
// Calls f(point)
template <typename F>
void for_each_l_to_r(F f) const {
int anc_depth = floor_log_2((a - 1) ^ b);
int anc_msk = (1 << anc_depth) - 1;
for (int v = (-a) & anc_msk; v; v &= v - 1) {
int i = countr_zero(unsigned(v));
f(point(((a - 1) >> i) + 1));
}
for (int v = b & anc_msk; v;) {
int i = floor_log_2(v);
f(point((b >> i) - 1));
v ^= (1 << i);
}
}
// Iterate over the range from right to left.
// Calls f(point)
template <typename F>
void for_each_r_to_l(F f) const {
int anc_depth = floor_log_2((a - 1) ^ b);
int anc_msk = (1 << anc_depth) - 1;
for (int v = b & anc_msk; v; v &= v - 1) {
int i = countr_zero(unsigned(v));
f(point((b >> i) - 1));
}
for (int v = (-a) & anc_msk; v;) {
int i = floor_log_2(v);
f(point(((a - 1) >> i) + 1));
v ^= (1 << i);
}
}
template <typename F>
void for_parents_down(F f) const {
int x = a, y = b;
if ((x ^ y) > x) {
x <<= 1, std::swap(x, y);
}
int dx = countr_zero(unsigned(x));
int dy = countr_zero(unsigned(y));
int anc_depth = floor_log_2((x - 1) ^ y);
for (int i = floor_log_2(x); i > dx; i--) {
f(point(x >> i));
}
for (int i = anc_depth; i > dy; i--) {
f(point(y >> i));
}
}
template <typename F>
void for_parents_up(F f) const {
int x = a, y = b;
if ((x ^ y) > x) {
x <<= 1, std::swap(x, y);
}
int dx = countr_zero(unsigned(x));
int dy = countr_zero(unsigned(y));
int anc_depth = floor_log_2((x - 1) ^ y);
for (int i = dx + 1; i <= anc_depth; i++) {
f(point(x >> i));
}
for (int v = y >> (dy + 1); v; v >>= 1) {
f(point(v));
}
}
};
struct in_order_layout {
// Alias them in for convenience
using point = seg_tree::point;
using range = seg_tree::range;
int n, s;
in_order_layout() : n(0), s(0) {}
in_order_layout(int n_) : n(n_), s(n ? bit_ceil(unsigned(n)) : 0) {}
point get_point(int a) const {
assert(0 <= a && a < n);
a += s;
return point(a >= 2 * n ? a - n : a);
}
range get_range(int a, int b) const {
assert(0 <= a && a <= b && b <= n);
if (n == 0) return range();
a += s, b += s;
return range((a >= 2 * n ? 2 * (a - n) : a), (b >= 2 * n ? 2 * (b - n) : b));
}
range get_range(std::array<int, 2> p) const {
return get_range(p[0], p[1]);
}
int get_leaf_index(point pt) const {
int a = int(pt);
assert(n <= a && a < 2 * n);
return (a < s ? a + n : a) - s;
}
std::array<int, 2> get_node_bounds(point pt) const {
int a = int(pt);
assert(1 <= a && a < 2 * n);
int l = countl_zero(unsigned(a)) - countl_zero(unsigned(2 * n - 1));
int x = a << l, y = (a + 1) << l;
assert(s <= x && x < y && y <= 2 * s);
return {(x >= 2 * n ? (x >> 1) + n : x) - s, (y >= 2 * n ? (y >> 1) + n : y) - s};
}
int get_node_split(point pt) const {
int a = int(pt);
assert(1 <= a && a < n);
int l = countl_zero(unsigned(2 * a + 1)) - countl_zero(unsigned(2 * n - 1));
int x = (2 * a + 1) << l;
assert(s <= x && x < 2 * s);
return (x >= 2 * n ? (x >> 1) + n : x) - s;
}
int get_node_size(point pt) const {
auto bounds = get_node_bounds(pt);
return bounds[1] - bounds[0];
}
};
struct circular_layout {
// Alias them in for convenience
using point = seg_tree::point;
using range = seg_tree::range;
int n;
circular_layout() : n(0) {}
circular_layout(int n_) : n(n_) {}
point get_point(int a) const {
assert(0 <= a && a < n);
return point(n + a);
}
range get_range(int a, int b) const {
assert(0 <= a && a <= b && b <= n);
if (n == 0) return range();
return range(n + a, n + b);
}
range get_range(std::array<int, 2> p) const {
return get_range(p[0], p[1]);
}
int get_leaf_index(point pt) const {
int a = int(pt);
assert(n <= a && a < 2 * n);
return a - n;
}
// Returns {x,y} so that 0 <= x < n and 1 <= y <= n
// If the point is non-wrapping, then 0 <= x < y <= n
std::array<int, 2> get_node_bounds(point pt) const {
int a = int(pt);
assert(1 <= a && a < 2 * n);
int l = countl_zero(unsigned(a)) - countl_zero(unsigned(2 * n - 1));
int s = bit_ceil(unsigned(n));
int x = a << l, y = (a + 1) << l;
assert(s <= x && x < y && y <= 2 * s);
return {(x >= 2 * n ? x >> 1 : x) - n, (y > 2 * n ? y >> 1 : y) - n};
}
// Returns the split point of the node, such that 1 <= s <= n.
int get_node_split(point pt) const {
int a = int(pt);
assert(1 <= a && a < n);
return get_node_bounds(pt.c(0))[1];
}
int get_node_size(point pt) const {
auto bounds = get_node_bounds(pt);
int r = bounds[1] - bounds[0];
return r > 0 ? r : r + n;
}
};
} // namespace seg_tree
template <typename Info>
class SimpleSegmentTree {
public:
int n;
vector<Info> infos;
seg_tree::in_order_layout layout;
void UpdateNode(seg_tree::point a) {
infos[a] = infos[a.c(0)].Unite(infos[a.c(1)]);
}
SimpleSegmentTree(int n_) : SimpleSegmentTree(vector<Info>(n_)) {}
SimpleSegmentTree(const vector<Info>& a) : n(int(a.size())) {
assert(n > 0);
infos.resize(2 * n);
layout = seg_tree::in_order_layout(n);
for (int i = 0; i < n; i++) {
infos[layout.get_point(i)] = a[i];
}
for (int i = n - 1; i >= 1; i--) {
infos[i] = infos[2 * i].Unite(infos[2 * i + 1]);
}
}
void Set(int p, const Info& v) {
auto pt = layout.get_point(p);
infos[pt] = v;
pt.for_parents_up([&](seg_tree::point a) {
UpdateNode(a);
});
}
Info Query(int l, int r) {
auto rng = layout.get_range(l, r);
Info res;
rng.for_each_l_to_r([&](seg_tree::point a) {
res = res.Unite(infos[a]);
});
return res;
}
Info Get(int p) {
auto pt = layout.get_point(p);
return infos[pt];
}
template <typename F>
int MaxRight(int l, F f) {
auto rng = layout.get_range(l, n);
int res = n;
Info sum;
rng.for_each_l_to_r([&](seg_tree::point a) {
if (res != n) {
return;
}
auto new_sum = sum.Unite(infos[a]);
if (f(new_sum)) {
sum = new_sum;
return;
}
while (a < n) {
new_sum = sum.Unite(infos[a.c(0)]);
if (f(new_sum)) {
sum = new_sum;
a = a.c(1);
} else {
a = a.c(0);
}
}
res = layout.get_node_bounds(a)[0];
});
return res;
}
template <typename F>
int MinLeft(int r, F f) {
auto rng = layout.get_range(0, r);
int res = 0;
Info sum;
rng.for_each_r_to_l([&](seg_tree::point a) {
if (res != 0) {
return;
}
auto new_sum = infos[a].Unite(sum);
if (f(new_sum)) {
sum = new_sum;
return;
}
while (a < n) {
new_sum = infos[a.c(1)].Unite(sum);
if (f(new_sum)) {
sum = new_sum;
a = a.c(0);
} else {
a = a.c(1);
}
}
res = layout.get_node_bounds(a)[1];
});
return res;
}
};
struct Info {
int mx = 0, cnt = 0;
ll sum = 0;
Info Unite(Info b) const {
Info res;
res.mx = std::max(mx, b.mx), res.cnt = cnt + b.cnt, res.sum = sum + b.sum;
return res;
}
static Info GetDefault([[maybe_unused]] int l, [[maybe_unused]] int r) {
return Info();
}
};
// signed main() {
int main() {
// freopen(".in", "r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
std::cin >> n >> m;
vi a(n), b(m), al;
for (auto& i : a) std::cin >> i, al.eb(i);
for (auto& i : b) std::cin >> i, al.eb(i);
std::sort(all(b), greater());
b.resize(n, -Big * 2);
std::sort(all(al));
al.erase(std::unique(all(al)), al.end());
int N = sz(al);
vl sa(n + 1), sb(m + 1);
for (int i = 0; i < n; i++) sa[i + 1] = sa[i] + a[i], a[i] = lwb(al, a[i]);
for (int i = 0; i < m; i++) sb[i + 1] = sb[i] + b[i], b[i] = lwb(al, b[i]);
SimpleSegmentTree<Info> tr(n);
vi buc(N);
for (int i = 0; i < n; i++) buc[a[i]]++;
for (int i = 1; i < N; i++) buc[i] += buc[i - 1];
buc.insert(buc.begin(), 0), buc.pop_back();
auto add = [&](int x) {
tr.Set(buc[x]++, Info{x, 1, al[x]});
};
auto del = [&](int x) {
tr.Set(--buc[x], Info{0, 0, 0});
};
int L = 0, R = -1;
auto div = [&](this auto&& div, int l, int r, int pl, int pr) -> ll {
debug(l, r, pl, pr);
if (l > r) return -BIG;
int mid = l + r >> 1;
while (L > pl) add(a[--L]);
while (R < std::min(mid, pr)) add(a[++R]);
while (L < pl) del(a[L++]);
while (R > std::min(mid, pr)) del(a[R--]);
ll ans = -BIG;
int p;
while (L <= std::min(mid, pr)) {
int k = tr.MaxRight(0, [&](const Info& x) {
debug(x.cnt);
if (x.cnt == 0) return true;
return x.mx < b[x.cnt - 1];
});
auto c = tr.Query(0, k);
ll ansnow = sa[mid + 1] - sa[L] - c.sum + sb[c.cnt];
if (ckmax(ans, ansnow)) p = L;
del(a[L++]);
}
return std::max({ans, div(l, mid - 1, pl, p), div(mid + 1, r, p, pr)});
};
std::cout << div(0, n - 1, 0, n - 1);
return 0;
}
/*
找到最后一个 k 满足 a_k<b_k a从小到大排序 b从大到小排序 满足单调性 线段树二分
注意处理a相等的情况
*/