Submission #1298713

#TimeUsernameProblemLanguageResultExecution timeMemory
1298713marvinthangFlooding Wall (BOI24_wall)C++17
100 / 100
2107 ms32524 KiB
/************************************* * author: marvinthang * * created: 03.12.2025 20:26:43 * *************************************/ #include <bits/stdc++.h> using namespace std; #define fi first #define se second #define left ___left___ #define right ___right___ #define scan_op(...) istream & operator >> (istream &in, __VA_ARGS__ &u) #define print_op(...) ostream & operator << (ostream &out, const __VA_ARGS__ &u) #define file(name) if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); } #ifdef LOCAL #include "debug.h" #else #define DB(...) #define db(...) "" #define debug(...) #endif namespace std { template <class U, class V> scan_op(pair <U, V>) { return in >> u.first >> u.second; } template <class T> scan_op(vector <T>) { for (size_t i = 0; i < u.size(); ++i) in >> u[i]; return in; } template <class U, class V> print_op(pair <U, V>) { return out << '(' << u.first << ", " << u.second << ')'; } template <size_t i, class T> ostream &print_tuple_utils(ostream &out, const T &tup) { if constexpr(i == tuple_size<T>::value) return out << ")"; else return print_tuple_utils<i + 1, T>(out << (i ? ", " : "(") << get<i>(tup), tup); } template <class...U> print_op(tuple <U...>) { return print_tuple_utils<0, tuple <U...>>(out, u); } template <class Con, class = decltype(begin(declval<Con>()))>typename enable_if <!is_same<Con, string>::value, ostream &>::type operator << (ostream &out, const Con &con) { out << '{'; for (__typeof(con.begin()) it = con.begin(); it != con.end(); ++it) out << (it == con.begin() ? "" : ", ") << *it; return out << '}'; } template <class T> print_op(stack <T>) { vector <T> v; stack <T> st = u; while (!st.empty()) v.push_back(st.top()), st.pop(); reverse(v.begin(), v.end()); return out << v; } template <class T> print_op(queue <T>) { queue <T> q = u; out << '{'; while (!q.empty()) { out << q.front(); q.pop(); if (!q.empty()) out << ", "; } out << '}'; return out; } template <class T, class X, class Y> print_op(priority_queue <T, X, Y>) { priority_queue <T, X, Y> pq = u; out << '{'; while (!pq.empty()) { out << pq.top(); pq.pop(); if (!pq.empty()) out << ", "; } out << '}'; return out; } template <class Fun> class y_combinator_result { Fun fun_; public: template <class T> explicit y_combinator_result(T &&fun): fun_(forward<T>(fun)) {} template <class...Args> decltype(auto)operator()(Args &&...args) { return fun_(ref(*this), forward<Args>(args)...); } }; template <class Fun> decltype(auto)y_combinator(Fun &&fun) { return y_combinator_result<decay_t<Fun>>(forward<Fun>(fun)); } template <typename T, int D> struct Vec: public vector <Vec<T, D - 1>> { static_assert(D >= 1, "Vector dimension must be greater than zero!"); template <typename ...Args> Vec(int n = 0, Args ...args): vector <Vec<T, D - 1>>(n, Vec<T, D - 1>(args...)) {} }; template <typename T> struct Vec<T, 1>: public vector<T>{ Vec(int n = 0, const T &val = T()): vector<T>(n, val) {} }; #if __cplusplus < 202002L template <class T> int ssize(const T &a) { return a.size(); } #endif } namespace MODINT { struct barrett { unsigned int _m; unsigned long long im; explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {} unsigned int umod() const { return _m; }; unsigned int mul(unsigned int a, unsigned int b) const { unsigned long long z = a; z *= b; unsigned long long x = (unsigned long long)(((unsigned __int128) z * im) >> 64); unsigned long long y = x * _m; return (unsigned int)(z - y + (z < y ? _m : 0)); } }; template <class T> T invGeneral(T a, T b) { a %= b; if (!a) return b == 1 ? 0 : -1; T x = invGeneral(b, a); return x == -1 ? -1 : ((1 - 1LL * b * x) / a + b) % b; } template <int m, enable_if_t<1 <= m>* = nullptr> struct static_modint { using mint = static_modint; public: static constexpr int mod() { return m; } static mint raw(int v) { mint x; x.v = v; return x; } static_modint(): v(0) {} template <class T> static_modint(T x) { int y; if (x < 0) { if (x < -mod()) y = x % mod(); else y = x; if (y < 0) y += mod(); } else { if (x < mod()) y = x; else y = x % mod(); } v = y; } unsigned int val() const { return v; } unsigned int operator () () const { return v; } mint & operator ++ () { if (++v == umod()) v = 0; return *this; } mint & operator -- () { if (!v) v = umod(); --v; return *this; } mint operator ++ (int) { mint old = *this; ++*this; return old; } mint operator -- (int) { mint old = *this; --*this; return old; } mint operator + () { return *this; } mint operator - () { return raw(!v ? 0 : umod() - v); } mint & operator += (const mint &rhs) { v += rhs.v; if (v >= umod()) v -= umod(); return *this; } mint & operator -= (const mint &rhs) { v -= rhs.v; if (v >= umod()) v += umod(); return *this; } mint & operator *= (const mint &rhs) { unsigned long long z = v; z *= rhs.v; v = z % umod(); return *this; } mint & operator /= (const mint &rhs) { return *this *= rhs.inv(); } friend mint operator + (const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; } friend mint operator - (const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; } friend mint operator * (const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; } friend mint operator / (const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; } mint pow(long long n) const { assert(0 <= n); mint res = 1, a = *this; for (; n; n >>= 1, a *= a) if (n & 1) res *= a; return res; } mint inv() const { int i = invGeneral((int) v, mod()); assert(~i); return i; } friend bool operator == (const mint& lhs, const mint& rhs) { return lhs.v == rhs.v; } friend bool operator != (const mint& lhs, const mint& rhs) { return lhs.v != rhs.v; } friend ostream & operator << (ostream &out, const mint &x) { return out << x.v; } friend istream & operator >> (istream &in, mint &x) { long long a; in >> a; x = a; return in; } explicit operator bool() const { return v; } explicit operator int() const { return v; } private: unsigned int v; static constexpr unsigned int umod() { return m; } }; template <int id> struct dynamic_modint { using mint = dynamic_modint; public: static int mod() { return (int) bt.umod(); } static void set_mod(int m) { assert(1 <= m); bt = barrett(m); } static mint raw(int v) { mint x; x.v = v; return x; } dynamic_modint(): v(0) {} template <class T> dynamic_modint(T x) { int y; if (x < 0) { if (x < -mod()) y = x % mod(); else y = x; if (y < 0) y += mod(); } else { if (x < mod()) y = x; else y = x % mod(); } v = y; } unsigned int val() const { return v; } unsigned int operator () () const { return v; } mint & operator ++ () { if (++v == umod()) v = 0; return *this; } mint & operator -- () { if (!v) v = umod(); --v; return *this; } mint operator ++ (int) { mint old = *this; ++*this; return old; } mint operator -- (int) { mint old = *this; --*this; return old; } mint operator + () { return *this; } mint operator - () { return raw(!v ? 0 : umod() - v); } mint & operator += (const mint &rhs) { v += rhs.v; if (v >= umod()) v -= umod(); return *this; } mint & operator -= (const mint &rhs) { v -= rhs.v; if (v >= umod()) v += umod(); return *this; } mint & operator *= (const mint &rhs) { v = bt.mul(v, rhs.v); return *this; } mint & operator /= (const mint &rhs) { return *this *= rhs.inv(); } friend mint operator + (const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; } friend mint operator - (const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; } friend mint operator * (const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; } friend mint operator / (const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; } mint pow(long long n) const { assert(0 <= n); mint res = 1, a = *this; for (; n; n >>= 1, a *= a) if (n & 1) res *= a; return res; } mint inv() const { int i = invGeneral((int) v, mod()); assert(~i); return i; } friend bool operator == (const mint& lhs, const mint& rhs) { return lhs.v == rhs.v; } friend bool operator != (const mint& lhs, const mint& rhs) { return lhs.v != rhs.v; } friend ostream & operator << (ostream &out, const mint &x) { return out << x.v; } friend istream & operator >> (istream &in, mint &x) { long long a; in >> a; x = a; return in; } explicit operator bool() const { return v; } explicit operator int() const { return v; } private: unsigned int v; static barrett bt; static unsigned int umod() { return bt.umod(); } }; template <int id> barrett dynamic_modint<id>::bt(998244353); using modint998244353 = static_modint<998244353>; using modint1000000007 = static_modint<1000000007>; using modint = dynamic_modint <-1>; using Modular = modint1000000007; } using namespace MODINT; template < class S, // node data type S (*op) (S, S), // combine 2 nodes S (*e) (), // identity element class F, // lazy propagation tag S (*mapping) (F, S), // apply tag F on a node F (*composition) (F, F), // combine 2 tags F (*id)() // identity tag > struct LazySegTree { LazySegTree() : LazySegTree(0) {} LazySegTree(int n) : LazySegTree(vector<S>(n, e())) {} LazySegTree(const vector <S> &v) : n(v.size()) { log = 0; while ((1 << log) < n) ++log; size = 1 << log; d = vector<S>(size << 1, e()); lz = vector<F>(size, id()); for (int i = 0; i < n; ++i) d[i + size] = v[i]; for (int i = size - 1; i > 0; --i) update(i); } // 0 <= p < n void set(int p, S x) { assert(0 <= p && p < n); p += size; for (int i = log; i > 0; --i) push(p >> i); d[p] = x; for (int i = 1; i <= log; ++i) update(p >> i); } // 0 <= p < n S get(int p) { assert(0 <= p && p < n); p += size; for (int i = log; i > 0; --i) push(p >> i); return d[p]; } // Get product in range [l, r-1] // 0 <= l <= r <= n // For empty segment (l == r) -> return e() S prod(int l, int r) { assert(0 <= l && l <= r && r <= n); if (l == r) return e(); l += size; r += size; for (int i = log; i > 0; --i) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S all_prod() { return d[1]; } // 0 <= p < n void apply(int p, F f) { assert(0 <= p && p < n); p += size; for (int i = log; i > 0; --i) push(p >> i); d[p] = mapping(f, d[p]); for (int i = 1; i <= log; ++i) update(p >> i); } // Apply f on all elements in range [l, r-1] // 0 <= l <= r <= n void apply(int l, int r, F f) { assert(0 <= l && l <= r && r <= n); if (l == r) return; l += size; r += size; for (int i = log; i > 0; --i) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; for (int i = 1; i <= log; ++i) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } // Binary search on SegTree to find largest r: // f(op(a[l] .. a[r-1])) = true (assuming empty array is always true) // f(op(a[l] .. a[r])) = false (assuming op(..., a[n]), which is out of bound, is always false) template <bool (*g)(S)> int max_right(int l) { return max_right(l, [](S x) { return g(x); }); } template <class G> int max_right(int l, G g) { assert(0 <= l && l <= n); assert(g(e())); if (l == n) return n; l += size; for (int i = log; i > 0; --i) push(l >> i); S sm = e(); do { while (!(l & 1)) l >>= 1; if (!g(op(sm, d[l]))) { while (l < size) { push(l); l = l << 1; if (g(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return n; } // Binary search on SegTree to find smallest l: // f(op(a[l] .. a[r-1])) = true (assuming empty array is always true) // f(op(a[l-1] .. a[r-1])) = false (assuming op(a[-1], ..), which is out of bound, is always false) template <bool (*g)(S)> int min_left(int r) { return min_left(r, [](S x) { return g(x); }); } template <class G> int min_left(int r, G g) { assert(0 <= r && r <= n); assert(g(e())); if (!r) return 0; r += size; for (int i = log; i > 0; --i) push((r - 1) >> i); S sm = e(); do { r--; while (r > 1 && (r & 1)) r >>= 1; if (!g(op(d[r], sm))) { while (r < size) { push(r); r = r << 1 | 1; if (g(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int n, size, log; vector<S> d; vector<F> lz; void update(int k) { d[k] = op(d[k << 1], d[k << 1 | 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(k << 1, lz[k]); all_apply(k << 1 | 1, lz[k]); lz[k] = id(); } }; template< class T, // data type for nodes T (*op) (T, T), // operator to combine 2 nodes T (*e)() // identity element > struct SegTree { SegTree(): SegTree(0) {} SegTree(int n) : SegTree(vector<T>(n, e())) {} SegTree(const vector <T>& v) : n(v.size()) { log = 0; while ((1 << log) < n) ++log; size = 1 << log; d = vector<T>(size << 1, e()); for (int i = 0; i < n; ++i) d[size + i] = v[i]; for (int i = size - 1; i > 0; --i) update(i); } // 0 <= p < n void set(int p, T x) { assert(0 <= p && p < n); p += size; d[p] = x; for (int i = 1; i <= log; ++i) update(p >> i); } // 0 <= p < n T get(int p) const { assert(0 <= p && p < n); return d[p + size]; } // Get product in range [l, r-1] // 0 <= l <= r <= n // For empty segment (l == r) -> return e() T prod(int l, int r) const { assert(0 <= l && l <= r && r <= n); T sml = e(), smr = e(); l += size; r += size; while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } T all_prod() const { return d[1]; } // Binary search on SegTree to find largest r: // f(op(a[l] .. a[r-1])) = true (assuming empty array is always true) // f(op(a[l] .. a[r])) = false (assuming op(..., a[n]), which is out of bound, is always false) template <bool (*f)(T)> int max_right(int l) const { return max_right(l, [](T x) { return f(x); }); } template <class F> int max_right(int l, F f) const { assert(0 <= l && l <= n); assert(f(e())); if (l == n) return n; l += size; T sm = e(); do { while (!(l & 1)) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = l << 1; if (f(op(sm, d[l]))) { sm = op(sm, d[l]); l++; } } return l - size; } sm = op(sm, d[l]); l++; } while ((l & -l) != l); return n; } // Binary search on SegTree to find smallest l: // f(op(a[l] .. a[r-1])) = true (assuming empty array is always true) // f(op(a[l-1] .. a[r-1])) = false (assuming op(a[-1], ..), which is out of bound, is always false) template <bool (*f)(T)> int min_left(int r) const { return min_left(r, [](T x) { return f(x); }); } template <class F> int min_left(int r, F f) const { assert(0 <= r && r <= n); assert(f(e())); if (r == 0) return 0; r += size; T sm = e(); do { r--; while (r > 1 && (r & 1)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = r << 1 | 1; if (f(op(d[r], sm))) { sm = op(d[r], sm); r--; } } return r + 1 - size; } sm = op(d[r], sm); } while ((r & -r) != r); return 0; } private: int n, size, log; vector <T> d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; // end of template Modular sum(Modular a, Modular b) { return a + b; } Modular zero() { return 0; } Modular mul(Modular f, Modular x) { return x * f; } Modular one() { return 1; } void process(void) { int n; cin >> n; vector <int> a(n), b(n); cin >> a >> b; vector <pair <int, int>> lst; for (int i = 0; i < n; ++i) { lst.emplace_back(a[i], i); lst.emplace_back(b[i], i); } sort(lst.rbegin(), lst.rend()); Modular res; Modular inv2 = Modular(2).inv(); vector <Modular> init(n, 2); LazySegTree<Modular, sum, zero, Modular, mul, mul, one> left(n), right(n); SegTree<Modular, mul, one> mul(init); vector <int> cnt(n); int last = lst.back().first; for (auto [h, i]: lst) { res += (last - h) * (left.all_prod() + right.all_prod()); res -= h * Modular(2).pow(n - 1); if (!cnt[i]) { left.set(i, (-i + 1) * Modular(2).pow(n - i - 1) * mul.prod(0, i)); left.apply(i + 1, n, inv2); right.set(i, i * Modular(2).pow(i) * mul.prod(i + 1, n)); right.apply(0, i, inv2); } else { left.apply(i, i + 1, 2); left.apply(i + 1, n, 0); right.apply(i, i + 1, 2); right.apply(0, i, 0); } ++cnt[i]; mul.set(i, 2 - cnt[i]); last = h; } res += last * (left.all_prod() + right.all_prod()); cout << res << '\n'; } int main(void) { ios_base::sync_with_stdio(false); cin.tie(nullptr); // cout.tie(nullptr); file("wall"); // int t; cin >> t; while (t--) process(); // cerr << "Time elapsed: " << TIME << " s.\n"; return (0^0); }

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:16:62: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   16 | #define     file(name)  if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:526:9: note: in expansion of macro 'file'
  526 |         file("wall");
      |         ^~~~
Main.cpp:16:95: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   16 | #define     file(name)  if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                                                        ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:526:9: note: in expansion of macro 'file'
  526 |         file("wall");
      |         ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...