結果
問題 |
No.3207 Digital Font
|
ユーザー |
![]() |
提出日時 | 2025-07-18 23:35:58 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 15,419 bytes |
コンパイル時間 | 3,790 ms |
コンパイル使用メモリ | 279,100 KB |
実行使用メモリ | 53,556 KB |
最終ジャッジ日時 | 2025-07-18 23:36:33 |
合計ジャッジ時間 | 21,004 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 25 WA * 13 |
コンパイルメッセージ
In member function ‘WMSum<T, Weight_t>& WMSum<T, Weight_t>::operator=(WMSum<T, Weight_t>) [with T = int; Weight_t = modint61]’, inlined from ‘void WMRectangleSum<Weight_t, x_lookup, y_lookup>::build() [with Weight_t = modint61; bool x_lookup = true; bool y_lookup = false]’ at main.cpp:335:12: main.cpp:219:28: warning: ‘<anonymous>.WMSum<int, modint61>::log’ may be used uninitialized [-Wmaybe-uninitialized] 219 | N = wm.N, log = wm.log; | ~~~^~~ main.cpp: In member function ‘void WMRectangleSum<Weight_t, x_lookup, y_lookup>::build() [with Weight_t = modint61; bool x_lookup = true; bool y_lookup = false]’: main.cpp:335:14: note: ‘<anonymous>’ declared here 335 | wm = WMSum<int, Weight_t>(ny, W); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
ソースコード
#include <algorithm> #include <array> #include <bit> #include <cassert> #include <chrono> #include <cmath> #include <concepts> #include <cstddef> #include <cstdint> #include <cstdlib> #include <deque> #include <functional> #include <iomanip> #include <iostream> #include <iterator> #include <limits> #include <map> #include <numeric> #include <optional> #include <queue> #include <random> #include <ranges> #include <set> #include <sstream> #include <stdexcept> #include <string> #include <tuple> #include <type_traits> #include <utility> #include <vector> struct IOSetup { IOSetup() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(15); std::cerr << std::fixed << std::setprecision(8); } }; IOSetup iosetup; using int128_t = __int128; using uint128_t = unsigned __int128; template <typename T> constexpr auto rep_iota_impl(T start, T stop) noexcept { return std::views::iota(start, (start < stop ? stop : start)); } template <typename T = int64_t> constexpr auto rep_impl(auto stop) noexcept { return rep_iota_impl<T>(0, stop); } template <class... Ts> inline void read(Ts&... ts) { (std::cin >> ... >> ts); } template <typename T> void unique_inplace(std::vector<T>& A) { if (!std::is_sorted(A.begin(), A.end())) { std::sort(A.begin(), A.end()); } A.erase(std::unique(A.begin(), A.end()), A.end()); } using std::vector; template <typename X> struct MAdd { using ll = int64_t; using T = X; static constexpr T op(const T& x, const T& y) noexcept { return x + y; } static constexpr T inverse(const T& x) noexcept { return -x; } static constexpr T power(const T& x, ll n) noexcept { return T{x} * n; } static constexpr T unit() noexcept { return T{}; } static constexpr bool is_unit(const T& x) noexcept { return x == T{}; } static constexpr bool commutative = true; }; template <typename MX, typename T = typename MX::T, typename U> vector<T> accumulate(vector<T> A, U initial) { vector<T> res(A.size() + 1); res[0] = T{initial}; for (const auto i : rep_impl((A.size()))) { res[i + 1] = MX::op(res[i], A[i]); } return res; } template <typename T, typename U> vector<T> accumulate(vector<T>& A, U initial) { return accumulate<MAdd<T>>(A, initial); } using std::vector; inline void put(const char* s) { std::cout << s; } template <typename... Ts> void print(const Ts&... ts) { put(ts...); std::cout << "\n"; } using std::cin; using std::cout; using std::map; using std::pair; using std::set; using std::string; using std::tuple; using std::vector; using ll = int64_t; using std::vector; struct BitVector { uint32_t N; vector<std::pair<uint64_t, uint32_t>> data; bool frozen = false; int64_t ones = 0; BitVector(int N_) : N(N_), data((N + 127) / 64) {} void set(int i) { assert(!frozen); assert(0 <= i && i < N); data[i / 64].first |= uint64_t{1} << (i % 64); } void build() { assert(!frozen); frozen = true; for (const auto q : rep_impl((data.size() - 1))) { data[q + 1].second = data[q].second + std::popcount(data[q].first); } ones = count1(N); } inline int count1(int k) const { assert(frozen); assert(0 <= k && k <= N); return data[k / 64].second + std::popcount(data[k / 64].first & ((uint64_t{1} << (k % 64)) - 1)); } inline int count0(int k) const { return k - count1(k); } inline int count0() const { assert(frozen); return N - ones; } }; using std::pair; using std::tuple; using std::vector; template <typename T, bool unique, bool lookup = false> class Compress { private: vector<T> X; vector<int> counter; bool frozen = false; public: Compress() {} template <typename U> Compress(const vector<U>& A) { extend(A); } void add(T x) { frozen = false; X.push_back(x); } template <typename U> void extend(const vector<U>& A) { frozen = false; X.reserve(X.size() + A.size()); for (const auto& x : A) { X.push_back(x); } } void build() { if (frozen) return; if (!std::is_sorted(X.begin(), X.end())) { std::sort(X.begin(), X.end()); } if constexpr (unique) { unique_inplace(X); } if constexpr (lookup) { if (!X.empty()) { auto min_ = X.front(); auto max_ = X.back(); counter.resize(max_ - min_ + 1, 0); for (const auto& x : X) { counter[x - min_] += 1; } counter = accumulate(counter, 0); } } frozen = true; } int64_t bisect_left(T x) const { assert(frozen); if (X.empty()) return 0; if (x <= X.front()) return 0; if (x > X.back()) return X.size(); if constexpr (lookup) { return counter[x - X.front()]; } else { return std::distance(X.begin(), std::lower_bound(X.begin(), X.end(), x)); } } int64_t bisect_right(T x) const { assert(frozen); if (X.empty()) return 0; if (x < X.front()) return 0; if (x >= X.back()) return X.size(); if constexpr (lookup) { return counter[x - X.front() + 1]; } else { return std::distance(X.begin(), std::upper_bound(X.begin(), X.end(), x)); } } int64_t size() const { return X.size(); } T operator[](int64_t idx) const { return X[idx]; } const vector<T>& sorted() const { return X; } }; template <typename T, typename Weight_t> struct WMSum { using ll = int64_t; int N, log; vector<T> data; T minval, maxval; vector<BitVector> Vs; vector<vector<Weight_t>> Ss; vector<Weight_t> W; WMSum() {} WMSum(const vector<T>& A, const vector<Weight_t>& W) : N(A.size()), data(A), W(W) {} WMSum& operator=(WMSum wm) { N = wm.N, log = wm.log; data = wm.data; Vs = wm.Vs; Ss = wm.Ss; W = wm.W; return *this; } void build() { log = 0; if (N == 0) return; minval = *min_element(data.begin(), data.end()); maxval = *max_element(data.begin(), data.end()); while ((T(1) << log) < (maxval - minval + 1)) log++; vector<T> A = data; for (auto& a : A) { a -= minval; } vector<Weight_t> S(N + 1, 0); for (int i = 0; i < N; i++) { S[i + 1] += S[i] + W[i]; } Ss.push_back(S); vector<int> I(N); for (int i = 0; i < N; i++) I[i] = i; for (int exp = log - 1; exp > -1; exp--) { BitVector V(N); vector<int> I0, I1; for (int pos = 0; pos < N; pos++) { auto i = I[pos]; auto a = A[i]; if ((a >> exp) & 1) { I1.push_back(i); V.set(pos); } else { I0.push_back(i); } } V.build(); Vs.push_back(V); I = I0; I.insert(I.end(), I1.begin(), I1.end()); vector<Weight_t> S(N + 1, 0); for (int pos = 0; pos < N; pos++) { auto i = I[pos]; S[pos + 1] += S[pos] + W[i]; } Ss.push_back(S); } std::reverse(Vs.begin(), Vs.end()); std::reverse(Ss.begin(), Ss.end()); } Weight_t sum_lt(pair<int, int> Irange, T x) const { auto [l, r] = Irange; if (l < 0) l = 0; if (r > N) r = N; if (l >= r) return 0; if (x < minval) return 0; if (x > maxval) return Ss[log][r] - Ss[log][l]; x -= minval; Weight_t res = 0; for (int exp = log - 1; exp > -1; exp--) { auto& S = Ss[exp]; auto& V = Vs[exp]; auto l0 = V.count0(l), r0 = V.count0(r); if ((x >> exp) & 1) { res += S[r0] - S[l0]; l += V.count0() - l0; r += V.count0() - r0; } else { l = l0; r = r0; } } return res; } }; template <typename Weight_t, bool x_lookup = false, bool y_lookup = false> struct WMRectangleSum { using ll = int64_t; vector<ll> X; vector<ll> Y; vector<Weight_t> W; vector<tuple<ll, ll, Weight_t>> XYW; Compress<ll, false, x_lookup> Cx; Compress<ll, true, y_lookup> Cy_uniq; bool frozen = false; int length; WMSum<int, Weight_t> wm; vector<pair<ll, ll>> XY; WMRectangleSum() {} void register_point(ll x, ll y, Weight_t w) { assert(!frozen); XYW.push_back({x, y, w}); } void build() { assert(!frozen); length = XYW.size(); std::sort(XYW.begin(), XYW.end()); X.reserve(length); Y.reserve(length); W.reserve(length); for (auto [x, y, w] : XYW) { X.push_back(x); Y.push_back(y); W.push_back(w); Cx.add(x); Cy_uniq.add(y); } XYW.clear(); Cx.build(), Cy_uniq.build(); vector<int> ny; for (auto y : Y) { ny.push_back(Cy_uniq.bisect_left(y)); } wm = WMSum<int, Weight_t>(ny, W); wm.build(); frozen = true; } Weight_t rectangle_sum(pair<ll, ll> Xrange, pair<ll, ll> Yrange) { auto [x1, x2] = Xrange; if (x1 >= x2) { return Weight_t{}; } auto [y1, y2] = Yrange; if (y1 >= y2) { return Weight_t{}; } int i1 = Cx.bisect_left(x1), i2 = Cx.bisect_left(x2); int j1 = Cy_uniq.bisect_left(y1), j2 = Cy_uniq.bisect_left(y2); if (i1 >= i2) { return Weight_t{}; } if (j1 >= j2) { return Weight_t{}; } Weight_t res = wm.sum_lt({i1, i2}, j2); res -= wm.sum_lt({i1, i2}, j1); return res; } }; inline uint32_t nanoseconds() { auto now = std::chrono::high_resolution_clock::now(); auto duration = now.time_since_epoch(); auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration); uint32_t rv = nanoseconds.count(); return rv; } inline uint32_t randtime32() { static constexpr uint64_t MULT = 0x9E3779B97F4A7C15; static uint64_t rv = 123456789; rv ^= nanoseconds(); for (int i = 0; i < 20; ++i) { rv ^= rv << 13, rv ^= rv >> 17, rv ^= rv << 5; rv *= MULT; rv *= i * i + 1; rv += 1; } return uint32_t(rv); } inline uint64_t randtime64() { return uint64_t(randtime32()) << 32 | randtime32(); } inline uint64_t random64() { using uint128_t = __uint128_t; static constexpr uint64_t MULT = 0xfeb3'4465'7c0a'f413; static uint64_t x2 = randtime64(); static uint64_t x3 = 0xcafe'f00d'd15e'a5e5; static uint128_t c_x1 = uint128_t(0x1405'7b7e'f767'814f) << 64 | randtime64(); uint128_t x = (uint128_t)(x3)*MULT; uint64_t result = (x3 ^ x2) + ((uint64_t)(c_x1) ^ (uint64_t)(x >> 32)); x3 = x2; x2 = (uint64_t)(c_x1); c_x1 = x + (c_x1 >> 64); return result; } inline uint64_t random64(uint64_t stop) { assert(stop > 0); return random64() % stop; } inline uint64_t random64(uint64_t start, uint64_t stop) { assert(start < stop); return start + random64(stop - start); } struct modint61 { static constexpr uint64_t MOD = (1ULL << 61) - 1; using mint = modint61; using uint128_t = __uint128_t; private: uint64_t _v = 0; static constexpr uint64_t pow_mod(uint64_t base, uint64_t exp) noexcept { uint64_t res = 1; while (exp) { if (exp & 1) { const uint128_t y = static_cast<uint128_t>(res) * base; res = (y >> 61) + (y & MOD); if (res >= MOD) res -= MOD; } const uint128_t y = static_cast<uint128_t>(base) * base; base = (y >> 61) + (y & MOD); if (base >= MOD) base -= MOD; exp >>= 1; } return res; } public: static constexpr mint raw(uint64_t v) noexcept { mint a; a._v = v; return a; } constexpr modint61() {} constexpr modint61(int32_t v) : _v(v < 0 ? v + MOD : v) {} constexpr modint61(uint64_t v) : _v(v % MOD) {} constexpr mint& operator+=(mint rhs) { if (_v >= MOD - rhs._v) _v -= MOD; _v += rhs._v; return *this; } constexpr mint& operator-=(mint rhs) { if (_v < rhs._v) _v += MOD; _v -= rhs._v; return *this; } constexpr mint& operator*=(mint rhs) { const uint128_t y = static_cast<uint128_t>(_v) * rhs._v; _v = (y >> 61) + (y & MOD); if (_v >= MOD) _v -= MOD; return *this; } constexpr mint& operator/=(mint rhs) { const uint128_t y = static_cast<uint128_t>(_v) * pow_mod(rhs._v, MOD - 2); _v = (y >> 61) + (y & MOD); if (_v >= MOD) _v -= MOD; return *this; } friend constexpr mint operator+(mint lhs, mint rhs) { return lhs += rhs; } friend constexpr mint operator-(mint lhs, mint rhs) { return lhs -= rhs; } friend constexpr mint operator*(mint lhs, mint rhs) { return lhs *= rhs; } bool operator<(const mint& other) const { return _v < other._v; } bool operator==(const mint& p) const { return _v == p._v; } bool operator!=(const mint& p) const { return _v != p._v; } mint inv() const { return pow(MOD - 2); } mint pow(int64_t n) const { if (n < 0) return inv().pow(-n); return mint::raw(pow_mod(_v, n)); } }; using mint = modint61; int main() { int64_t H, W; read(H, W); int64_t N; read(N); vector<mint> A(10); for (const auto i : rep_impl((10))) A[i] = mint::raw(random64(1, uint64_t{1} << 60)); const mint base = mint::raw(random64(1, uint64_t{1} << 60)); const mint base2 = mint::raw(random64(1, uint64_t{1} << 60)); vector<ll> F(10); for (const auto i : rep_impl((10))) F[i] = i; F[6] = 9; F[9] = 6; vector<tuple<ll, ll, ll>> todo; for ([[maybe_unused]] const auto _i : rep_impl((N))) { int64_t i, j, x; read(i, j, x); i -= 1; j -= 1; todo.push_back({i, j, x}); } auto wm = WMRectangleSum<mint, 1, 0>(); auto wm2 = WMRectangleSum<mint, 1, 0>(); for (auto [i, j, x] : todo) { wm.register_point(i, j, mint{A[x]} * base.pow(i) * base2.pow(j)); ll ni = H - 1 - i, nj = W - 1 - j; wm2.register_point(ni, nj, mint{A[F[x]]} * base.pow(ni) * base2.pow(nj)); } wm.build(); wm2.build(); int64_t Q; read(Q); for ([[maybe_unused]] const auto _i : rep_impl((Q))) { int64_t L, D, R, U; read(L, D, R, U); L -= 1; D -= 1; mint hash = wm.rectangle_sum({L, R}, {D, U}); hash /= base.pow(L) * base2.pow(D); mint hash2 = wm2.rectangle_sum({H - R, H - L}, {W - U, W - D}); hash2 /= base.pow(H - R) * base2.pow(W - U); if (hash == hash2) { print("Yes"); } else { print("No"); } } }