結果
問題 | No.2762 Counting and Deleting |
ユーザー |
![]() |
提出日時 | 2025-01-10 22:54:11 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,982 ms / 4,000 ms |
コード長 | 9,745 bytes |
コンパイル時間 | 11,240 ms |
コンパイル使用メモリ | 334,172 KB |
実行使用メモリ | 42,240 KB |
最終ジャッジ日時 | 2025-01-10 22:54:43 |
合計ジャッジ時間 | 31,437 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 15 |
ソースコード
#include <bits/stdc++.h> #if __has_include(<atcoder/all>) #include <atcoder/all> std::istream &operator>>(std::istream &is, atcoder::modint &v) { long long value; is >> value; v = value; return is; } std::ostream &operator<<(std::ostream &os, const atcoder::modint &v) { os << v.val(); return os; } std::ostream &operator<<(std::ostream &os, const atcoder::modint998244353 &v) { os << v.val(); return os; } std::istream &operator>>(std::istream &is, atcoder::modint998244353 &v) { long long x; is >> x; v = x; return is; } std::ostream &operator<<(std::ostream &os, const atcoder::modint1000000007 &v) { os << v.val(); return os; } std::istream &operator>>(std::istream &is, atcoder::modint1000000007 &v) { long long x; is >> x; v = x; return is; } #endif using namespace std; using ll = long long; using pll = pair<ll, ll>; #define newl '\n'; #define rep(i, s, t) for (ll i = s; i < (ll)(t); i++) #define rrep(i, s, t) for (ll i = (ll)(t) - 1; i >= (ll)(s); i--) #define all(x) begin(x), end(x) #define eb emplace_back #define pb push_back #define TT template <typename T> TT using vec = vector<T>; TT using vvec = vec<vec<T>>; TT using vvvec = vec<vvec<T>>; TT using minheap = priority_queue<T, vector<T>, greater<T>>; TT using maxheap = priority_queue<T>; TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; } TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; } TT bool rng(T l, T x, T r) { return l <= x && x < r; } TT T flr(T a, T b) { if (b < 0) a = -a, b = -b; return a >= 0 ? a / b : (a + 1) / b - 1; } TT T cil(T a, T b) { if (b < 0) a = -a, b = -b; return a > 0 ? (a - 1) / b + 1 : a / b; } TT T sqr(T x) { return x * x; } struct io_setup { io_setup() { ios::sync_with_stdio(false); std::cin.tie(nullptr); cout << fixed << setprecision(15); } } io_setup; template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p) { os << p.first << " " << p.second; return os; } TT ostream &operator<<(ostream &os, const vec<T> &v) { for (size_t i = 0; i < v.size(); i++) { os << v[i] << (i + 1 != v.size() ? " " : ""); } return os; } template <typename T, ll n> ostream &operator<<(ostream &os, const array<T, n> &v) { for (size_t i = 0; i < n; i++) { os << v[i] << (i + 1 != n ? " " : ""); } return os; } template <typename T> ostream &operator<<(ostream &os, const vvec<T> &v) { for (size_t i = 0; i < v.size(); i++) { os << v[i] << (i + 1 != v.size() ? "\n" : ""); } return os; } TT istream &operator>>(istream &is, vec<T> &v) { for (size_t i = 0; i < v.size(); i++) { is >> v[i]; } return is; } #if __has_include(<debug/debug.hpp>) #include <debug/debug.hpp> #else #define dbg(...) true #define DBG(...) true #define OUT(...) true #endif template <typename T, bool merge_adju> struct rangeset : public std::map<T, T> { rangeset() {} auto get(T p) const { auto it = (*this).upper_bound(p); if (it == (*this).begin() || (--it)->second <= p) return (*this).end(); return it; } //[l, r) void insert(T l, T r) { if (l == r) return; assert(l <= r); auto itl = (*this).upper_bound(l), itr = (*this).lower_bound(r + merge_adju); if (itl != (*this).begin() && (--itl)->second + merge_adju <= l) { ++itl; } if (itl != itr) { if (itl->first < l) l = itl->first; if (prev(itr)->second > r) r = prev(itr)->second; map<T, T>::erase(itl, itr); } (*this)[l] = r; } //[l, r) void erase(T l, T r) { if (l == r) return; assert(l <= r); auto itl = (*this).upper_bound(l), itr = (*this).lower_bound(r); if (itl != (*this).begin() && (--itl)->second <= l) { ++itl; } if (itl == itr) return; T tl = l, tr = r; if (itl->first < l) tl = itl->first; if (prev(itr)->second > r) tr = prev(itr)->second; map<T, T>::erase(itl, itr); if (tl < l) (*this)[tl] = l; if (tr > r) (*this)[r] = tr; } bool contains(T p) const { return get(p) != (*this).end(); } bool same(T a, T b) const { if (a > b) swap(a, b); auto it = get(a); if (it == (*this).end()) return false; return b < it->second; } T mex(T x = 0) const { auto it = get(x); if (it == (*this).end()) return x; else return it->second; } template <typename TYPE, bool ME> friend ostream &operator<<(ostream &os, rangeset<TYPE, ME> const &rhs) { for (auto [l, r] : rhs) os << "[" << l << ", " << r << ")"; return os; } }; template <typename T> struct Matrix { int h, w; vector<vector<T>> d; Matrix() {} Matrix(int h, int w, T val = 0) : h(h), w(w), d(h, vector<T>(w, val)) {} Matrix(vector<vector<T>> const &dat) : h(dat.size()), w(0), d(dat) { if (h > 0) w = d[0].size(); } static Matrix unit(int n) { Matrix uni(n, n, 0); rep(i, 0, n) { uni[i][i] = 1; } return uni; } const vector<T> &operator[](int i) const { return d[i]; } vector<T> &operator[](int i) { return d[i]; } Matrix &operator*=(const Matrix &a) { return *this = (*this) * a; } Matrix operator*(const Matrix &a) const { assert(w == a.h); Matrix r(h, a.w); rep(i, 0, h) { rep(k, 0, w) { rep(j, 0, a.w) { r[i][j] += d[i][k] * a[k][j]; } } } return r; } Matrix pow(ll t) const { assert(h == w); Matrix res = Matrix::unit(h); Matrix x = (*this); while (t > 0) { if (t & 1) res = res * x; x = x * x; t >>= 1; } return res; } tuple<Matrix, T, ll> gaussian_elimination(int w_limit = -1) const { if (w_limit == -1) w_limit = w; T k = 1; Matrix A = *this; int i1 = 0; for (int j = 0; j < w_limit; j++) { if (i1 >= h) break; for (int i2 = i1; i2 < h; i2++) { if (A[i2][j] != 0) { swap(A[i1], A[i2]); if (i1 != i2) k = -k; break; } } if (A[i1][j] == 0) { continue; } T inv = 1 / A[i1][j]; k *= A[i1][j]; for (int jj = 0; jj < w; jj++) { A[i1][jj] *= inv; } for (int i = 0; i < h; i++) if (A[i][j] != 0 && i != i1) { T c = -A[i][j]; for (int jj = 0; jj < w; jj++) { A[i][jj] += A[i1][jj] * c; } } i1++; } return make_tuple(A, k, i1); } ll rank() const { auto [dat, k, rnk] = (*this).gaussian_elimination(); return rnk; } pair<vector<T>, bool> linear_equations() const { assert(h == w - 1); vector<T> ret(w - 1); auto [dat, p, rnk] = (*this).gaussian_elimination(w - 1); if (rnk != w - 1) return make_pair(ret, false); rep(i, 0, h) { ret[i] = dat[i][w - 1]; } return make_pair(ret, true); } pair<Matrix, bool> inv() const { assert(h == w); Matrix slv(h, w * 2); for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) { slv[i][j] = (*this)[i][j]; } for (int i = 0; i < h; i++) { slv[i][i + w] = 1; } auto [dat, p, rnk] = slv.gaussian_elimination(w); auto ret = Matrix::unit(h); if (rnk != h) return make_pair(ret, false); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { ret[i][j] = dat[i][j + w]; } } return make_pair(ret, true); } T det() const { assert(h == w); auto [A, p, rnk] = (*this).gaussian_elimination(); rep(i, 0, h) p *= A[i][i]; return p; } friend ostream &operator<<(ostream &os, Matrix a) { for (int i = 0; i < a.h; i++) { for (int j = 0; j < a.w; j++) { os << a[i][j] << (j != a.w - 1 ? " " : ""); } os << (i != a.h - 1 ? "\n" : ""); } return os; } }; using mint = atcoder::modint998244353; Matrix<mint> op(Matrix<mint> l, Matrix<mint> r) { return r * l; } Matrix<mint> e() { return Matrix<mint>::unit(3); } int main() { ll n, q; cin >> n >> q; string S; cin >> S; Matrix<mint> one = vvec<mint>{{1, 0, 1}, {0, 1, 1}, {0, 0, 1}}; Matrix<mint> zero = vvec<mint>{{1, 1, 0}, {0, 1, 0}, {0, 1, 1}}; atcoder::segtree<Matrix<mint>, op, e> seg(n); rep(i, 0, n) { if (S[i] == '0') seg.set(i, zero); else seg.set(i, one); } Matrix<mint> first = vvec<mint>{{1}, {0}, {1}}; set<int> remain; rep(i, 0, n) remain.insert(i); //DBG(zero*first); //DBG(one*first); while (q--) { ll t, l, r; cin >> t >> l >> r; l--; if (t == 1) { auto it = remain.lower_bound(l); while(it != remain.end() && (*it) < r) { seg.set(*(it), Matrix<mint>::unit(3)); remain.erase(it++); } } else { auto ret = seg.prod(l, r); auto ret2 = ret * first; //DBG(ret); //dbg(ret2); cout << ret2[0][0] - 1 << endl; } } }