#include namespace MyLib { template class LiteralSegmentTree { protected: std::vector> containers; public: constexpr LiteralSegmentTree(const std::vector& initializer) { containers.clear(); if (initializer.size() == 0) [[unlikely]] return; else if (initializer.size() == 1) [[unlikely]] { containers.emplace_back(1, initializer[0]); return; } uint_fast32_t l = 0, r = 30; while (l + 1 < r) { const auto c = (l + r) >> 1; if (((uint_fast32_t)1 << c) < initializer.size()) l = c; else r = c; } containers.emplace_back((uint_fast32_t)1 << r); uint_fast32_t i; for (i = 0; i != initializer.size(); ++i) containers[0][i] = initializer[i]; for (; i != ((uint_fast32_t)1 << r); ++i) containers[0][i] = default_value; for (--r; r != 0; --r) { containers.emplace_back((uint_fast32_t)1 << r); [[assume(containers.size() >= 2)]]; for (i = 0; i != ((uint_fast32_t)1 << r); ++i) containers[containers.size() - 1][i] = Picker()(containers[containers.size() - 2][i << 1], containers[containers.size() - 2][(i << 1) | 1]); } containers.emplace_back(1, Picker()(containers[containers.size() - 1][0], containers[containers.size() - 1][1])); } constexpr LiteralSegmentTree(std::vector&& initializer) { containers.clear(); if (initializer.size() == 0) [[unlikely]] return; uint_fast32_t l = 0, r = 30; while (l + 1 < r) { const auto c = (l + r) >> 1; if (((uint_fast32_t)1 << c) < initializer.size()) l = c; else r = c; } containers.emplace_back(std::move(initializer)); containers[0].resize((uint_fast32_t)1 << r, default_value); uint_fast32_t i; for (--r; r != 0; --r) { containers.emplace_back((uint_fast32_t)1 << r); [[assume(containers.size() >= 2)]]; for (i = 0; i != ((uint_fast32_t)1 << r); ++i) containers[containers.size() - 1][i] = Picker()(containers[containers.size() - 2][i << 1], containers[containers.size() - 2][(i << 1) | 1]); } containers.emplace_back(1, Picker()(containers[containers.size() - 1][0], containers[containers.size() - 1][1])); } constexpr LiteralSegmentTree(const uint_fast32_t n) : LiteralSegmentTree(std::vector(n, default_value)) { } constexpr LiteralSegmentTree(const uint_fast32_t n, const T initial_value) : LiteralSegmentTree(std::vector(n, initial_value)) { } [[nodiscard]] constexpr T operator[](uint_fast32_t index) const noexcept { return containers[0][index]; } [[nodiscard]] constexpr uint_fast32_t size() const noexcept { return containers[0].size(); } [[nodiscard]] constexpr uint_fast32_t layer() const noexcept { return containers.size(); } constexpr T update(uint_fast32_t index, const T value) noexcept { containers[0][index] = value; index >>= 1; for (uint_fast32_t i = 1; i != containers.size(); ++i, index >>= 1) containers[i][index] = Picker()(containers[i - 1][index << 1], containers[i - 1][(index << 1) | 1]); return value; } [[nodiscard]] constexpr T range_pick_up(uint_fast32_t first_index, uint_fast32_t end_index) const noexcept { if (containers.size() == 0 || end_index > containers[0].size()) [[unlikely]] return default_value; T ret_l = default_value, ret_r = default_value; for (uint_fast32_t cur_layer = 0; first_index < end_index; first_index >>= 1, end_index >>= 1, ++cur_layer) { if (first_index & 1) ret_l = Picker()(ret_l, containers[cur_layer][first_index]), ++first_index; if (end_index & 1) ret_r = Picker()(containers[cur_layer][end_index - 1], ret_r); } return Picker()(ret_l, ret_r); } }; template using DefaultMaxPicker = decltype([](const T a, const T b) { return std::max(a, b); }); template::lowest()> class MaxSegmentTree : public LiteralSegmentTree { public: constexpr MaxSegmentTree(const std::vector& initializer) : LiteralSegmentTree(initializer) { } constexpr MaxSegmentTree(std::vector&& initializer) : LiteralSegmentTree(std::move(initializer)) { } template constexpr MaxSegmentTree(const Args... args) : LiteralSegmentTree(std::forward(args)...) { } [[nodiscard]] constexpr uint_fast32_t leftest_above(const uint_fast32_t first, const uint_fast32_t last, const T limit) const noexcept { [[assume(first <= last)]]; if (this->containers.size() == 0) [[unlikely]] return 0; uint_fast32_t cur_layer, cur_index; uint_fast32_t candidate_layer = this->containers.size(), candidate_index; uint_fast32_t first_temp = first, last_temp = last; for (cur_layer = 0; first_temp != last_temp; ++cur_layer, first_temp >>= 1, last_temp >>= 1) { if (first_temp & 1) { if (this->containers[cur_layer][first_temp] >= limit) break; ++first_temp; } if (last_temp & 1) { [[assume(last_temp >= 1)]]; if (this->containers[cur_layer][last_temp - 1] >= limit) candidate_layer = cur_layer, candidate_index = last_temp - 1; //--last_temp; } } if (first_temp != last_temp) cur_index = first_temp; else if (candidate_layer == this->containers.size()) return this->containers[0].size(); else cur_layer = candidate_layer, cur_index = candidate_index; while (cur_layer != 0) { --cur_layer, cur_index <<= 1; if (this->containers[cur_layer][cur_index] < limit) cur_index |= 1; } return cur_index; } [[nodiscard]] constexpr uint_fast32_t rightest_above(const uint_fast32_t first, const uint_fast32_t last, const T limit) const noexcept { [[assume(first <= last)]]; if (this->containers.size() == 0) [[unlikely]] return 0; uint_fast32_t cur_layer, cur_index; uint_fast32_t candidate_layer = this->containers.size(), candidate_index; uint_fast32_t first_temp = first, last_temp = last; for (cur_layer = 0; first_temp != last_temp; ++cur_layer, first_temp >>= 1, last_temp >>= 1) { if (last_temp & 1) { [[assume(last_temp >= 1)]]; if (this->containers[cur_layer][last_temp - 1] >= limit) break; //--last_temp; } if (first_temp & 1) { if (this->containers[cur_layer][first_temp] >= limit) candidate_layer = cur_layer, candidate_index = first_temp; ++first_temp; } } if (first_temp != last_temp) cur_index = last_temp - 1; else if (candidate_layer == this->containers.size()) return this->containers[0].size(); else cur_layer = candidate_layer, cur_index = candidate_index; while (cur_layer != 0) { --cur_layer, cur_index <<= 1; if (this->containers[cur_layer][cur_index | 1] >= limit) cur_index |= 1; } return cur_index; } }; } [[nodiscard]] static inline constexpr uint_fast32_t prepare(const uint_fast32_t N, const uint_fast32_t M, const std::vector& S, const std::vector& T) noexcept { [[assume(std::is_sorted(S.begin(), S.end()))]]; MyLib::MaxSegmentTree, 0> unused_S(S); for (uint_fast32_t x = 0; x != M; ++x) { const auto index = unused_S.leftest_above(0, N, T[x]); if (index >= N) return x; unused_S.update(index, 0); } return M; } [[nodiscard]] static inline constexpr uint_fast32_t solve(const uint_fast32_t N, const uint_fast32_t M, const std::vector& S, std::vector& T) noexcept { [[assume(std::is_sorted(S.begin(), S.end()))]]; const uint_fast32_t x = prepare(N, M, S, T); std::sort(T.begin(), T.begin() + x); uint_fast32_t ans = 0; for (uint_fast32_t i = 0, j = 0; j != x; ++i, ++j) { while (S[i] < T[j]) ++i; ans = std::max(ans, S[i] - T[j]); } return ans; } int main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); uint_fast32_t N, M; std::cin >> N >> M; std::vector S(N), T(M); for (auto& s : S) std::cin >> s; for (auto& t : T) std::cin >> t; std::sort(S.begin(), S.end()); std::cout << solve(N, M, S, T) << '\n'; return 0; }