結果
問題 |
No.3207 Digital Font
|
ユーザー |
|
提出日時 | 2025-07-18 22:54:36 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,636 ms / 3,000 ms |
コード長 | 7,079 bytes |
コンパイル時間 | 5,399 ms |
コンパイル使用メモリ | 279,744 KB |
実行使用メモリ | 24,288 KB |
最終ジャッジ日時 | 2025-07-18 22:55:23 |
合計ジャッジ時間 | 40,203 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 38 |
ソースコード
#include<bits/stdc++.h> using namespace std; // from: https://drken1215.hatenablog.com/entry/2023/10/20/015537 // Bit Vector (for 64-bit non-negative integer) struct BitVector { // block: bit vector // count: the number of 1 within each block unsigned int n, zeros; vector<unsigned long long> block; vector<unsigned int> count; // constructor BitVector() {} BitVector(const unsigned int num) { resize(num); } void resize(const unsigned int num) { n = num; block.assign(((num + 1) >> 6) + 1, 0); count.assign(block.size(), 0); } // set val(0 or 1) onto i-th bit, get i-th bit of val(0 or 1) void set(const unsigned int i, const unsigned long long val = 1LL) { assert((i >> 6) < block.size()); block[i >> 6] |= (val << (i & 63)); } unsigned int get(const unsigned int i) const { assert((i >> 6) < block.size()); return (const unsigned int)(block[i >> 6] >> (i & 63)) & 1; } void build() { for (unsigned int i = 1; i < block.size(); i++) { count[i] = count[i - 1] + __builtin_popcountll(block[i - 1]); } zeros = rank0(n); } // the number of 1 in [0, i) unsigned int rank1(const unsigned int i) const { assert((i >> 6) < count.size()); assert((i >> 6) < block.size()); return count[i >> 6] + __builtin_popcountll(block[i >> 6] & ((1ULL << (i & 63)) - 1ULL)); } // the number of 1 in [i, j) unsigned int rank1(const unsigned int i, const unsigned int j) const { return rank1(j) - rank1(i); } // the number of 0 in [0, i) unsigned int rank0(const unsigned int i) const { return i - rank1(i); } // the number of 0 in [i, j) unsigned int rank0(const unsigned int i, const unsigned int j) const { return rank0(j) - rank0(i); } // the number of 0 in [0, n) unsigned int rank0() const { return zeros; } }; // BIT on Wavelet Matrix template<class POS, class VAL> struct BITonWaveletMatrix { // inner data struct BIT { VAL UNITY_SUM = 0; int N; vector<VAL> dat; // [0, n) BIT() {} BIT(int n, VAL unity = 0) : UNITY_SUM(unity), N(n), dat(n, unity) { } void init(int n) { N = n; dat.assign(n, UNITY_SUM); } // a is 0-indexed void add(int a, VAL x) { for (int i = a; i < (int)dat.size(); i |= i + 1) dat[i] = dat[i] + x; } // [0, a), a is 0-indexed VAL sum(int a) { VAL res = UNITY_SUM; for (int i = a - 1; i >= 0; i = (i & (i + 1)) - 1) res = res + dat[i]; return res; } // [a, b), a and b are 0-indexed VAL sum(int a, int b) { return sum(b) - sum(a); } // debug void print() { for (int i = 0; i < (int)dat.size(); ++i) cout << sum(i, i + 1) << ","; cout << endl; } }; using Point = pair<POS, POS>; int n, height; vector<BitVector> bv; vector<Point> ps; vector<POS> ys; vector<BIT> bit; // constructor (sigma: the number of characters) // add_point() cannot be used after build() BITonWaveletMatrix() {} BITonWaveletMatrix(const vector<Point> &vec) { for (auto [x, y] : vec) add_point(x, y); build(); } void add_point(POS x, POS y) { ps.emplace_back(x, y); ys.emplace_back(y); } int xid(POS x) const { return lower_bound(ps.begin(), ps.end(), Point(x, 0)) - ps.begin(); } int yid(POS y) const { return lower_bound(ys.begin(), ys.end(), y) - ys.begin(); } void build() { sort(ps.begin(), ps.end()); ps.erase(unique(ps.begin(), ps.end()), ps.end()); n = (int)ps.size(); sort(ys.begin(), ys.end()); ys.erase(unique(ys.begin(), ys.end()), ys.end()); vector<int> v(n), left(n), right(n), ord(n); int mv = 1; for (int i = 0; i < n; ++i) { v[i] = yid(ps[i].second); mv = max(mv, v[i]); } for (height = 1; mv != 0; mv >>= 1) ++height; iota(ord.begin(), ord.end(), 0); bv.assign(height, BitVector(n)); bit.assign(height + 1, BIT(n)); for (int h = height - 1; h >= 0; --h) { int l = 0, r = 0; for (int i = 0; i < n; ++i) { if ((v[ord[i]] >> h) & 1) { bv[h].set(i); right[r++] = ord[i]; } else { left[l++] = ord[i]; } } bv[h].build(); ord.swap(left); for (int i = 0; i < r; ++i) ord[i + l] = right[i]; } } // add void add(const POS x, const POS y, const VAL val) { int i = lower_bound(ps.begin(), ps.end(), Point(x, y)) - ps.begin(); int j = yid(y); for (int h = height - 1; h >= 0; --h) { int i0 = bv[h].rank0(i); if ((j >> h) & 1) { i += bv[h].rank0() - i0; } else { i = i0; } bit[h].add(i, val); } } // sum VAL inner_sum(int l, int r, const POS upper) { assert(0 <= l && r <= n); VAL res = 0; for (int h = height - 1; h >= 0; --h) { int l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); if ((upper >> h) & 1) { l += bv[h].rank0() - l0; r += bv[h].rank0() - r0; res += bit[h].sum(l0, r0); } else { l = l0; r = r0; } } return res; } VAL sum(const POS lx, const POS rx, const POS ly, const POS ry) { int l = xid(lx), r = xid(rx); return inner_sum(l, r, yid(ry)) - inner_sum(l, r, yid(ly)); } }; #include<atcoder/all> using mint=atcoder::modint998244353; int main(){ int h,w; cin>>h>>w; int n; cin>>n; BITonWaveletMatrix<int,mint> WM; int ix[n],iy[n],iz[n]; for(int i=0;i<n;i++){ cin>>ix[i]>>iy[i]>>iz[i]; ix[i]--;iy[i]--; WM.add_point(ix[i],iy[i]); } WM.build(); mint x=9967,y=9973; for(int i=0;i<n;i++){ WM.add(ix[i],iy[i],iz[i]*x.pow(ix[i])*y.pow(iy[i])); } BITonWaveletMatrix<int,mint> rWM; for(int i=0;i<n;i++){ rWM.add_point(h-ix[i]-1,w-iy[i]-1); } rWM.build(); auto flip=[](int v){ if(v==6) return 9; else if(v==9) return 6; else return v; }; for(int i=0;i<n;i++){ rWM.add(h-1-ix[i],w-1-iy[i],flip(iz[i])*x.pow(h-1-ix[i])*y.pow(w-1-iy[i])); } int q; cin>>q; //cerr<<WM.sum(0,0,1,1).val()<<endl; while(q--){ int l,d,r,u; cin>>l>>d>>r>>u; l--;d--; mint nv=WM.sum(l,r,d,u),rv=rWM.sum(h-r,h-l,w-u,w-d); nv/=x.pow(l)*y.pow(d); rv/=x.pow(h-r)*y.pow(w-u); if(nv==rv) cout<<"Yes\n"; else cout<<"No\n"; } }