#define USE_AC_LIBRARY #ifndef USE_AC_LIBRARY #include #elif defined(ONLINE_JUDGE) #include #include #else #include #endif using namespace std; using ll = long long; using uint = unsigned int; using ull = unsigned long long; namespace atcoder {}; using namespace atcoder; // for suisen-cp/cp-library-cpp namespace suisen {}; using namespace suisen; #ifdef ATCODER_MODINT_HPP using mint = modint998244353; #endif #define rep_kind(a, b, c, d, e, ...) e #define rep1(i, r) for (int i = 0; i < (int)(r); ++i) #define rep2(i, l, r) for (int i = (l); i < (int)(r); ++i) #define rep3(i, l, r, d) for (int i = (l); i < (int)(r); i += (d)) #define rep_r1(i, r) for (int i = (r) - 1; i >= 0; --i) #define rep_r2(i, l, r) for (int i = (r) - 1; i >= (l); --i) #define rep_r3(i, l, r, d) for (int i = (r) - 1; i >= (l); i -= (d)) #define rep(...) rep_kind(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__) #define rep_r(...) rep_kind(__VA_ARGS__, rep_r3, rep_r2, rep_r1)(__VA_ARGS__) #define rep_t_kind(a, b, c, d, e, f, ...) f #define rep_t1(type, i, r) for (type i = 0; i < (type)(r); ++i) #define rep_t2(type, i, l, r) for (type i = (l); i < (type)(r); ++i) #define rep_t3(type, i, l, r, d) for (type i = (l); i < (type)(r); i += (d)) #define rep_t_r1(type, i, r) for (type i = (r) - 1; i >= 0; --i) #define rep_t_r2(type, i, l, r) for (type i = (r) - 1; i >= (l); --i) #define rep_t_r3(type, i, l, r, d) for (type i = (r) - 1; i >= (l); i -= (d)) #define rep_t(...) rep_t_kind(__VA_ARGS__, rep_t3, rep_t2, rep_t1)(__VA_ARGS__) #define rep_t_r(...) \ rep_t_kind(__VA_ARGS__, rep_t_r3, rep_t_r2, rep_t_r1)(__VA_ARGS__) #define do_while_kind(a, b, c, ...) c #define do_while1(cond) \ for (bool is_first = true; is_first || (cond); is_first = false) #define do_while2(cond, is_first) \ for (bool is_first = true; is_first || (cond); is_first = false) #define do_while(...) \ do_while_kind(__VA_ARGS__, do_while2, do_while1)(__VA_ARGS__) #ifdef ATCODER_MODINT_HPP template istream &operator>>(istream &is, static_modint &x) { ll val; is >> val; x = val; return is; } template ostream &operator<<(ostream &os, const static_modint &x) { os << x.val(); return os; } template istream &operator>>(istream &is, dynamic_modint &x) { ll val; is >> val; x = val; return is; } template ostream &operator<<(ostream &os, const dynamic_modint &x) { os << x.val(); return os; } #endif inline int slot_index() { static int idx = ios_base::xalloc(); return idx; } struct separator { string s; }; inline separator sep(string s) { return {std::move(s)}; } inline void cleanup(ios_base::event ev, ios_base &ios, int idx) { void *&slot = ios.pword(idx); if (ev == ios_base::erase_event) { delete static_cast(slot); slot = nullptr; } else if (ev == ios_base::copyfmt_event) { if (auto *p = static_cast(slot); p) { slot = new string(*p); } } } inline ostream &operator<<(ostream &os, const separator &m) { void *&slot = os.pword(slot_index()); if (!slot) { slot = new string(m.s); os.register_callback(&cleanup, slot_index()); } else { *static_cast(slot) = m.s; } return os; } inline const char *current_sep(ios_base &ios) { if (auto p = static_cast(ios.pword(slot_index())); p) { return p->c_str(); } return " "; } template concept char_range = ranges::input_range && same_as, char>; template concept nonstring_range = ranges::input_range && !is_convertible_v, string_view> && !char_range; template concept writable_lvalue_range = is_lvalue_reference_v> && !is_const_v>>; template concept proxy_writable_range = !is_lvalue_reference_v> && !same_as>, ranges::range_value_t> && default_initializable> && requires(ranges::range_reference_t e, ranges::range_value_t v) { e = std::move(v); }; template concept inputtable_nonstring_range = nonstring_range && (writable_lvalue_range || proxy_writable_range); namespace io_detail { template concept tuple_like = requires { typename tuple_size>::type; }; template void read(istream &is, T &x); template void write(ostream &os, T &&x); template void for_each_tuple_element(Tuple &&t, F &&f) { [&](index_sequence) { using std::get; (f(get(std::forward(t))), ...); }(make_index_sequence>>{}); } template void read(istream &is, T &x) { if constexpr (inputtable_nonstring_range) { for (auto &&e : x) { if constexpr (writable_lvalue_range) { read(is, e); } else { ranges::range_value_t v{}; read(is, v); e = std::move(v); } } } else if constexpr (tuple_like) { for_each_tuple_element(x, [&](auto &e) { read(is, e); }); } else { is >> x; } } template void write(ostream &os, T &&x) { if constexpr (nonstring_range) { bool is_first = true; for (auto &&e : x) { if (is_first) { is_first = false; } else { os << current_sep(os); } write(os, std::forward(e)); } } else if constexpr (tuple_like) { bool is_first = true; for_each_tuple_element(std::forward(x), [&](auto &&e) { if (is_first) { is_first = false; } else { os << current_sep(os); } write(os, std::forward(e)); }); } else { os << std::forward(x); } } } // namespace io_detail template istream &operator>>(istream &is, pair &p) { io_detail::read(is, p); return is; } template ostream &operator<<(ostream &os, const pair &p) { io_detail::write(os, p); return os; } template istream &operator>>(istream &is, tuple &t) { io_detail::read(is, t); return is; } template ostream &operator<<(ostream &os, const tuple &t) { io_detail::write(os, t); return os; } template istream &operator>>(istream &is, T &r) { io_detail::read(is, r); return is; } template ostream &operator<<(ostream &os, T &&r) { io_detail::write(os, std::forward(r)); return os; } namespace incdec_detail { template inline constexpr bool always_false_v = false; template concept pre_incrementable = requires(T &x) { ++x; }; template concept pre_decrementable = requires(T &x) { --x; }; template concept tuple_like = requires { typename tuple_size>::type; }; template concept mutable_lvalue_range = ranges::input_range && is_lvalue_reference_v> && !is_const_v>>; template concept mutable_proxy_range = ranges::input_range && !is_lvalue_reference_v> && !same_as>, ranges::range_value_t> && constructible_from, ranges::range_reference_t> && requires(ranges::range_reference_t e, ranges::range_value_t v) { e = std::move(v); }; template void increment_impl(T &x); template void decrement_impl(T &x); template void for_each_tuple_element(Tuple &t, F &&f) { [&](index_sequence) { using std::get; (f(get(t)), ...); }(make_index_sequence>>{}); } template void increment_impl(T &x) { if constexpr (mutable_lvalue_range) { for (auto &&e : x) { increment_impl(e); } } else if constexpr (mutable_proxy_range) { for (auto &&e : x) { ranges::range_value_t v(e); increment_impl(v); e = std::move(v); } } else if constexpr (ranges::input_range) { static_assert(always_false_v); } else if constexpr (tuple_like) { for_each_tuple_element(x, [](auto &e) { increment_impl(e); }); } else if constexpr (pre_incrementable) { ++x; } else { static_assert(always_false_v); } } template void decrement_impl(T &x) { if constexpr (mutable_lvalue_range) { for (auto &&e : x) { decrement_impl(e); } } else if constexpr (mutable_proxy_range) { for (auto &&e : x) { ranges::range_value_t v(e); decrement_impl(v); e = std::move(v); } } else if constexpr (ranges::input_range) { static_assert(always_false_v); } else if constexpr (tuple_like) { for_each_tuple_element(x, [](auto &e) { decrement_impl(e); }); } else if constexpr (pre_decrementable) { --x; } else { static_assert(always_false_v); } } } // namespace incdec_detail template void increment(T &x) { incdec_detail::increment_impl(x); } template void decrement(T &x) { incdec_detail::decrement_impl(x); } template void in(Ts &...args) { (cin >> ... >> args); } template void in_z(Ts &...args) { in(args...); (decrement(args), ...); } namespace input_detail { template void read(Tuple &t) { apply( [](auto &...xs) { if constexpr (sizeof...(xs) > 0) { in(xs...); } }, t); } template void read_z(Tuple &t) { apply( [](auto &...xs) { if constexpr (sizeof...(xs) > 0) { in_z(xs...); } }, t); } template using repeat_t = T; template auto input_impl(index_sequence) { tuple...> t; read(t); return t; } template auto input_z_impl(index_sequence) { tuple...> t; read_z(t); return t; } } // namespace input_detail template auto input() { tuple t; in(t); return t; } template auto input_z() { tuple t; in_z(t); return t; } template auto input() { return input_detail::input_impl(make_index_sequence{}); } template auto input_z() { return input_detail::input_z_impl(make_index_sequence{}); } template void out(const Hd &hd, const Tl &...tl) { cout << hd; if constexpr (sizeof...(Tl)) { (cout << ... << (cout << current_sep(cout), tl)); } #ifdef ONLINE_JUDGE cout << "\n"; if constexpr (do_flush) { cout << flush; } #else cout << endl; #endif } template void out_and_flush(const Ts &...args) { out(args...); } template void err(const Hd &hd, const Tl &...tl) { #ifndef ONLINE_JUDGE cerr << hd; if constexpr (sizeof...(Tl)) { (cerr << ... << (cerr << current_sep(cerr), tl)); } cerr << "\n"; #endif } template void out2(It1 first, It2 last) { for (; first != last; ++first) { out(*first); } } template void out2(R &&range) { out2(begin(range), end(range)); } template void out2_and_flush(It1 first, It2 last) { out2(first, last); } template void out2_and_flush(R &&range) { out2(range); } template void err2(It1 first, It2 last) { #ifndef ONLINE_JUDGE for (; first != last; ++first) { err(*first); } #endif } template void err2(R &&range) { #ifndef ONLINE_JUDGE err2(begin(range), end(range)); #endif } auto &change_out_sep(string s = string()) { return cout << sep(s); } auto &change_err_sep(string s = string()) { return cerr << sep(s); } void change_seps(string s = string()) { change_out_sep(s); change_err_sep(s); } constexpr array dx_2{1, 0}, dy_2{0, 1}; constexpr array dx{1, 0, -1, 0}, dy{0, 1, 0, -1}; constexpr array dx_8{1, 1, 0, -1, -1, -1, 0, 1}, dy_8{0, 1, 1, 1, 0, -1, -1, -1}; namespace dir_detail { template constexpr auto zip(const array &xs, const array &ys) { array, N> res{}; for (size_t i = 0; i < N; ++i) { res[i] = {xs[i], ys[i]}; } return res; } }; // namespace dir_detail constexpr auto dxdy_2 = dir_detail::zip(dx_2, dy_2); constexpr auto dxdy = dir_detail::zip(dx, dy); constexpr auto dxdy_8 = dir_detail::zip(dx_8, dy_8); #define dir_2(dx_, dy_) for (auto [dx_, dy_] : dxdy_2) #define dir(dx_, dy_) for (auto [dx_, dy_] : dxdy) #define dir_8(dx_, dy_) for (auto [dx_, dy_] : dxdy_8) #define all(v) (v).begin(), (v).end() #define all_r(v) (v).rbegin(), (v).rend() #define iter(v, l, r) ((v).begin() + l), ((v).begin() + r) template void dedup(T &v) { v.erase(unique(all(v)), v.end()); } template void sort_and_dedup(T &v) { sort(all(v)); v.erase(unique(all(v)), v.end()); } constexpr string_view yes() { return "Yes"; } constexpr string_view no() { return "No"; } constexpr string_view yn(bool cond) { if (cond) { return yes(); } else { return no(); } } string yn(bool cond, const string &yes_str, const string &no_str) { if (cond) { return yes_str; } else { return no_str; } } template constexpr T yn(bool cond, const T &yes_val, const T &no_val) { if (cond) { return yes_val; } else { return no_val; } } template bool chmin(T1 &l, const T2 &r) { if (r < l) { l = r; return true; } return false; } template bool chmax(T1 &l, const T2 &r) { if (r > l) { l = r; return true; } return false; } template using sum_type_t = typename conditional_t, common_type, type_identity>::type; template using sum_init_type_t = typename conditional_t && is_arithmetic_v, common_type, U>, type_identity>::type; template auto sum_of(It first, It last) { using T = typename iterator_traits::value_type; return accumulate(first, last, sum_type_t{}); } template auto sum_of(It first, It last, U init) { using T = typename iterator_traits::value_type; using R = sum_init_type_t; return accumulate(first, last, R(init)); } template auto min_of(Hd1 hd1, Hd2 hd2, Tl... tl) { if constexpr (sizeof...(Tl) == 0) { return min(hd1, hd2); } else { return min(hd1, min_of(hd2, tl...)); } } template auto max_of(Hd1 hd1, Hd2 hd2, Tl... tl) { if constexpr (sizeof...(Tl) == 0) { return max(hd1, hd2); } else { return max(hd1, max_of(hd2, tl...)); } } template auto gcd_of(Hd1 hd1, Hd2 hd2, Tl... tl) { if constexpr (sizeof...(Tl) == 0) { return gcd(hd1, hd2); } else { return gcd(hd1, gcd_of(hd2, tl...)); } } template auto lcm_of(Hd1 hd1, Hd2 hd2, Tl... tl) { if constexpr (sizeof...(Tl) == 0) { return lcm(hd1, hd2); } else { return lcm(hd1, lcm_of(hd2, tl...)); } } namespace div_detail { template using uncv_t = remove_cv_t; template constexpr bool integral_non_bool_v = is_integral_v> && !is_same_v, bool>; template using common_t = common_type_t, uncv_t>; template using div_type_t = conditional_t> && (is_signed_v> || is_signed_v>), make_signed_t>, common_t>; template constexpr bool fits_in_div_type(From x) { using F = uncv_t; if constexpr (is_signed_v && is_unsigned_v) { using UTo = make_unsigned_t; return x <= static_cast(numeric_limits::max()); } else { return true; } } } // namespace div_detail template constexpr pair, div_detail::div_type_t> floor_div_mod(T1 x, T2 y) { static_assert(div_detail::integral_non_bool_v); static_assert(div_detail::integral_non_bool_v); assert(y != 0); using T = div_detail::div_type_t; assert(div_detail::fits_in_div_type(x)); assert(div_detail::fits_in_div_type(y)); T a = static_cast(x), b = static_cast(y); T q = a / b, r = a % b; if constexpr (is_signed_v) { if (r != 0 && ((r < 0) != (b < 0))) { --q; r += b; } } return pair{q, r}; } template constexpr div_detail::div_type_t floor_div(T1 x, T2 y) { static_assert(div_detail::integral_non_bool_v); static_assert(div_detail::integral_non_bool_v); assert(y != 0); return floor_div_mod(x, y).first; } template constexpr div_detail::div_type_t floor_mod(T1 x, T2 y) { static_assert(div_detail::integral_non_bool_v); static_assert(div_detail::integral_non_bool_v); assert(y != 0); return floor_div_mod(x, y).second; } template constexpr div_detail::div_type_t ceil_div(T1 x, T2 y) { static_assert(div_detail::integral_non_bool_v); static_assert(div_detail::integral_non_bool_v); assert(y != 0); using T = div_detail::div_type_t; auto [q, r] = floor_div_mod(x, y); return r == 0 ? q : static_cast(q + T{1}); } template auto make_vector(vector &sizes, T const &x) { if constexpr (N == 1) { return vector(sizes[0], x); } else { size_t size = sizes[N - 1]; sizes.pop_back(); return vector(size, make_vector(sizes, x)); } } template auto make_vector(size_t const (&sizes)[N], T const &x = T()) { vector s(N); rep(i, N) { s[i] = sizes[N - i - 1]; } return make_vector(s, x); } template auto make_vector(vector &sizes, T const &x) { if constexpr (N == 1) { return vector(sizes[0], x); } else { int size = sizes[N - 1]; sizes.pop_back(); return vector(size, make_vector(sizes, x)); } } template auto make_vector(int const (&sizes)[N], T const &x = T()) { vector s(N); rep(i, N) { s[i] = sizes[N - i - 1]; } return make_vector(s, x); } template auto make_array() { if constexpr (sizeof...(Tl) == 0) { return array{}; } else { return array()), Hd>{}; } } constexpr int inf32 = 1'000'000'001; constexpr ll inf64 = 2'000'000'000'000'000'001; constexpr ull ten_powers[20] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000ULL}; constexpr ull two_powers[64] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472, 274877906944, 549755813888, 1099511627776, 2199023255552, 4398046511104, 8796093022208, 17592186044416, 35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312, 1125899906842624, 2251799813685248, 4503599627370496, 9007199254740992, 18014398509481984, 36028797018963968, 72057594037927936, 144115188075855872, 288230376151711744, 576460752303423488, 1152921504606846976, 2305843009213693952, 4611686018427387904, 9223372036854775808ULL}; template class Heap = priority_queue> using min_heap = Heap, greater<>>; template constexpr S e_const() { return e; } template constexpr pair e_const_pair() { return {e1, e2}; } template S op_min(S a, S b) { return min(a, b); } template S op_max(S a, S b) { return max(a, b); } template pair op_minmax(pair a, pair b) { auto [a1, a2] = a; auto [b1, b2] = b; return {min(a1, b1), max(a2, b2)}; } template S op_add(S a, S b) { return a + b; } template pair op_add_pair(pair a, pair b) { auto [a1, a2] = a; auto [b1, b2] = b; return {a1 + b1, a2 + b2}; } template S mapping_affine(pair f, S x) { auto [a, b] = f; return a * x + b; } template pair mapping_minmax_affine(pair f, pair x) { auto [a, b] = f; auto [l, r] = x; if (a >= 0) { return {a * l + b, a * r + b}; } else { return {a * r + b, a * l + b}; } } template pair mapping_len_and_affine(pair f, pair x) { auto [a, b] = f; auto [x1, x2] = x; return {x1, a * x2 + b * x1}; } template pair composition_affine(pair f, pair g) { auto [a_f, b_f] = f; auto [a_g, b_g] = g; return {a_f * a_g, a_f * b_g + b_f}; } template constexpr M mint_const() { return M(e); } template constexpr pair mint_pair() { return {M1(e1), M2(e2)}; } #ifdef ATCODER_SEGTREE_HPP template using segtree_min = segtree, e_const>; template using segtree_max = segtree, e_const>; template using segtree_add = segtree, e_const>; template using segtree_add_mint = segtree, mint_const>; #endif #ifdef ATCODER_LAZYSEGTREE_HPP // f の傾きが非負であることを仮定する template using lazy_segtree_min = lazy_segtree, e_const, pair, mapping_affine, composition_affine, e_const_pair>; // f の傾きが非負であることを仮定する template using lazy_segtree_max = lazy_segtree, e_const, pair, mapping_affine, composition_affine, e_const_pair>; template using lazy_segtree_minmax = lazy_segtree, op_minmax, e_const_pair, pair, mapping_minmax_affine, composition_affine, e_const_pair>; template using lazy_segtree_add = lazy_segtree, op_add_pair, e_const_pair, pair, mapping_len_and_affine, composition_affine, e_const_pair>; template using lazy_segtree_add_mint = lazy_segtree, op_add_pair, mint_pair, pair, mapping_len_and_affine, composition_affine, mint_pair>; #endif // 数列を mod m 上で見たとき、区間に +1 または -1 を加える操作の最小回数を求める。 // 区間に整数 x を加える操作の最小 sum |x| と同値である。 // a, b は同じ長さで、各要素は [0, m) を仮定する。 // T は 64 bit 整数型、m <= 10^9 を想定する。 // 平均計算量 O(N)。 #include #include #include #include #include template T minimum_mod_range_increment_decrement_operations(const std::vector &a, const std::vector &b, T m) { static_assert(std::is_integral_v, "T must be integer."); static_assert(sizeof(T) >= sizeof(long long), "T must be at least 64-bit integer type."); assert(a.size() == b.size()); assert(m > 0); const std::size_t n = a.size(); std::vector differences; differences.reserve(n + 1); auto mod_difference = [m](T from, T to) -> T { return from <= to ? to - from : m - (from - to); }; auto add_mod_difference = [m](std::size_t "ient, T &remainder, T diff) { if (remainder >= m - diff) { remainder -= m - diff; ++quotient; } else { remainder += diff; } }; T previous = 0; std::size_t negative_count = 0; T remainder = 0; for (std::size_t i = 0; i < n; ++i) { if constexpr (std::is_signed_v) { assert(0 <= a[i]); assert(0 <= b[i]); } assert(a[i] < m); assert(b[i] < m); const T current = mod_difference(a[i], b[i]); const T diff = mod_difference(previous, current); differences.emplace_back(diff); add_mod_difference(negative_count, remainder, diff); previous = current; } const T last = mod_difference(previous, T(0)); differences.emplace_back(last); add_mod_difference(negative_count, remainder, last); assert(remainder == 0); assert(negative_count <= n + 1); const std::size_t keep_count = n + 1 - negative_count; if (0 < keep_count && keep_count < differences.size()) { std::nth_element(differences.begin(), differences.begin() + static_cast(keep_count), differences.end()); } T answer = 0; for (std::size_t i = 0; i < keep_count; ++i) { answer += differences[i]; } return answer; } void solve() { int n; ll m; ::in(n); std::vector a(n), b(n); ::in(m); rep(i, n) { ::in(a[i]); } rep(i, n) { ::in(b[i]); } out(minimum_mod_range_increment_decrement_operations(a, b, m)); } int main(void) { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(15); int t = 1; // ::in(t); while (t--) { solve(); } return 0; }