結果

問題 No.2762 Counting and Deleting
ユーザー maguroflymagurofly
提出日時 2024-05-09 13:41:31
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 655 ms / 4,000 ms
コード長 3,496 bytes
コンパイル時間 169 ms
コンパイル使用メモリ 82,396 KB
実行使用メモリ 124,312 KB
最終ジャッジ日時 2024-05-09 13:41:39
合計ジャッジ時間 6,631 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 41 ms
52,736 KB
testcase_01 AC 40 ms
53,248 KB
testcase_02 AC 39 ms
53,376 KB
testcase_03 AC 39 ms
53,376 KB
testcase_04 AC 41 ms
53,376 KB
testcase_05 AC 37 ms
52,864 KB
testcase_06 AC 38 ms
52,864 KB
testcase_07 AC 472 ms
109,612 KB
testcase_08 AC 527 ms
109,280 KB
testcase_09 AC 511 ms
110,556 KB
testcase_10 AC 655 ms
112,872 KB
testcase_11 AC 529 ms
124,312 KB
testcase_12 AC 566 ms
123,596 KB
testcase_13 AC 526 ms
122,020 KB
testcase_14 AC 538 ms
122,564 KB
testcase_15 AC 463 ms
98,548 KB
testcase_16 AC 416 ms
98,380 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys

def debug(text):
    print("\033[36m" + str(text) + "\033[m", file = sys.stderr)

MOD = 998244353

class BIT:
    def __init__(self, n):
        if type(n) is list:
            self.tree = [0] + n
            n = len(n)
            for v in range(1, n):
                p = v + (-v & v)
                if p <= n:
                    self.tree[p] += self.tree[v]
        else:
            self.tree = [0] * (n + 1)
        self.len = n
        self.depth = n.bit_length()
    
    def sum(self, l, r):
        return self.prefix_sum(r) - self.prefix_sum(l)
    
    def prefix_sum(self, r):
        s = 0
        while r > 0:
            s += self.tree[r]
            r -= -r & r
        return s
    
    def add(self, i, x):
        i += 1
        while i <= self.len:
            self.tree[i] += x
            i += -i & i
    
    # min(x for x in range(0, self.len) if self.prefix_sum(x) >= x)
    def lower_bound(self, x):
        if x == 0:
            return 0
        s = 0
        p = 0
        for i in range(self.depth, -1, -1):
            k = p + (1 << i)
            if k <= self.len and s + self.tree[k] < x:
                s += self.tree[k]
                p += 1 << i
        return p + 1

class Segtree:
    def op(self, x, y):
        a, b, c, d, e, f = x
        g, h, i, j, k, l = y
        return (
            (a * g + b * j) % MOD,
            (a * h + b * k) % MOD,
            (a * i + b * l + c) % MOD,
            (d * g + e * j) % MOD,
            (d * h + e * k) % MOD,
            (d * i + e * l + f) % MOD,
        )

    def e(self):
        return (1, 0, 0, 0, 1, 0)

    def __init__(self, a):
        if type(a) is int:
            a = [self.e()] * a
        n = len(a)
        size = 1
        while size < n: size <<= 1
        self.tree = [self.e()] * (size * 2)
        for i, x in enumerate(a):
            self.tree[size + i] = x
        for i in reversed(range(1, size)):
            self.tree[i] = self.op(self.tree[i << 1], self.tree[i << 1 | 1])
        self.size = size

    def __getitem__(self, p):
        return self.tree[self.size + p]

    def __setitem__(self, p, a):
        p += self.size
        self.tree[p] = a
        while p > 1:
            p >>= 1
            self.tree[p] = self.op(self.tree[p << 1], self.tree[p << 1 | 1])

    def fold(self, l, r):
        x = self.e()
        y = self.e()
        l += self.size
        r += self.size
        while l < r:
            if l & 1 != 0:
                x = self.op(x, self.tree[l])
                l += 1
            l >>= 1
            if r & 1 != 0:
                r -= 1
                y = self.op(self.tree[r], y)
            r >>= 1
        return self.op(x, y)

N, Q = map(int, input().split())
S = input()
queries = [list(map(int, input().split())) for _ in range(Q)]

A0 = (1, 1, 0, 0, 1, 0)
A1 = (1, 0, 0, 1, 1, 1)
A_ = (1, 0, 0, 0, 1, 0)

rest = BIT([1] * N)
seg = Segtree([A0 if S[N - 1 - i] == "0" else A1 for i in range(N)])

# debug(rest.tree)

for t, l, r in queries:
    l -= 1
    if t == 1:
        # debug(f"remove [{l}, {r})")
        while l < r:
            lb = rest.lower_bound(rest.prefix_sum(l) + 1)
            # debug(f"  lb={lb}")
            if lb == None or lb > r: break
            i = lb - 1
            seg[N - 1 - i] = A_
            rest.add(i, -1)
            l = lb
            # debug(f"  removed {i}")
    else:
        a, b, c, d, e, f = seg.fold(N - r, N - l)
        # debug((a, b, c, d, e, f))
        print((c + f) % MOD)
0