結果

問題 No.749 クエリ全部盛り
ユーザー lam6er
提出日時 2025-03-26 15:51:00
言語 PyPy3
(7.3.15)
結果
MLE  
実行時間 -
コード長 5,330 bytes
コンパイル時間 277 ms
コンパイル使用メモリ 82,688 KB
実行使用メモリ 847,716 KB
最終ジャッジ日時 2025-03-26 15:52:04
合計ジャッジ時間 10,050 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 15 MLE * 1 -- * 4
権限があれば一括ダウンロードができます

ソースコード

diff #

MOD = 10**9 + 7

def main():
    import sys
    input = sys.stdin.read().split()
    ptr = 0
    N = int(input[ptr]); ptr += 1
    Q = int(input[ptr]); ptr += 1

    # Precompute Fibonacci numbers and their prefix sums
    F = [0] * (N)
    S_F = [0] * (N)
    if N >= 1:
        F[0] = 0
        S_F[0] = 0
    if N >= 2:
        F[1] = 1
        S_F[1] = 1
    for i in range(2, N):
        F[i] = (F[i-1] + F[i-2]) % MOD
    for i in range(1, N):
        if i == 1:
            S_F[i] = F[i]
        else:
            S_F[i] = (S_F[i-1] + F[i]) % MOD

    class LazySegmentTree:
        def __init__(self, size):
            self.n = size
            self.size = 1
            while self.size < self.n:
                self.size <<= 1
            self.tree = [ {'sum_a':0, 'mul':1, 'add':0, 'fib_add':0} for _ in range(2 * self.size) ]
        
        def push(self, node, l, r):
            if node >= self.size:
                return
            current = self.tree[node]
            mul = current['mul']
            add = current['add']
            fib_add = current['fib_add']
            if mul == 1 and add == 0 and fib_add == 0:
                return
            left = 2 * node
            right = 2 * node + 1
            mid = (l + r) // 2

            len_left = mid - l + 1
            sum_F_left = (S_F[mid] - (S_F[l-1] if l > 0 else 0)) % MOD if mid < self.n else 0
            self.tree[left]['sum_a'] = (
                mul * self.tree[left]['sum_a'] +
                add * len_left +
                fib_add * sum_F_left
            ) % MOD
            self.tree[left]['mul'] = (mul * self.tree[left]['mul']) % MOD
            self.tree[left]['add'] = (mul * self.tree[left]['add'] + add) % MOD
            self.tree[left]['fib_add'] = (mul * self.tree[left]['fib_add'] + fib_add) % MOD

            len_right = r - (mid + 1) + 1
            rr = min(r, self.n - 1)
            sum_F_right = (S_F[rr] - (S_F[mid] if mid + 1 <= rr else 0)) % MOD if mid + 1 < self.n else 0
            self.tree[right]['sum_a'] = (
                mul * self.tree[right]['sum_a'] +
                add * len_right +
                fib_add * sum_F_right
            ) % MOD
            self.tree[right]['mul'] = (mul * self.tree[right]['mul']) % MOD
            self.tree[right]['add'] = (mul * self.tree[right]['add'] + add) % MOD
            self.tree[right]['fib_add'] = (mul * self.tree[right]['fib_add'] + fib_add) % MOD

            self.tree[node]['mul'] = 1
            self.tree[node]['add'] = 0
            self.tree[node]['fib_add'] = 0
        
        def range_update(self, a, b, mul_val, add_val, fib_val):
            stack = [(1, 0, self.size - 1, False)]
            while stack:
                node, l, r, processed = stack.pop()
                if not processed:
                    if b < l or a > r:
                        continue
                    if a <= l and r <= b:
                        len_seg = r - l + 1
                        rr = min(r, self.n - 1)
                        sum_F_seg = (S_F[rr] - (S_F[l-1] if l > 0 else 0)) % MOD if l < self.n else 0
                        self.tree[node]['sum_a'] = (
                            mul_val * self.tree[node]['sum_a'] +
                            add_val * len_seg +
                            fib_val * sum_F_seg
                        ) % MOD
                        self.tree[node]['mul'] = (mul_val * self.tree[node]['mul']) % MOD
                        self.tree[node]['add'] = (mul_val * self.tree[node]['add'] + add_val) % MOD
                        self.tree[node]['fib_add'] = (mul_val * self.tree[node]['fib_add'] + fib_val) % MOD
                        continue
                    self.push(node, l, r)
                    mid = (l + r) // 2
                    stack.append((node, l, r, True))
                    stack.append((2 * node + 1, mid + 1, r, False))
                    stack.append((2 * node, l, mid, False))
                else:
                    left = 2 * node
                    right_node = 2 * node + 1
                    self.tree[node]['sum_a'] = (self.tree[left]['sum_a'] + self.tree[right_node]['sum_a']) % MOD
        
        def range_query(self, a, b):
            res = 0
            stack = [(1, 0, self.size - 1)]
            while stack:
                node, l, r = stack.pop()
                if b < l or a > r:
                    continue
                if a <= l and r <= b:
                    res = (res + self.tree[node]['sum_a']) % MOD
                    continue
                self.push(node, l, r)
                mid = (l + r) // 2
                stack.append((2 * node + 1, mid + 1, r))
                stack.append((2 * node, l, mid))
            return res

    lst = LazySegmentTree(N)
    for _ in range(Q):
        q = int(input[ptr]); ptr +=1
        l = int(input[ptr]); ptr +=1
        r = int(input[ptr]); ptr +=1
        k = int(input[ptr]); ptr +=1
        if q == 0:
            sum_val = lst.range_query(l, r)
            print((sum_val * k) % MOD)
        elif q == 1:
            lst.range_update(l, r, 0, k, 0)
        elif q == 2:
            lst.range_update(l, r, 1, k, 0)
        elif q == 3:
            lst.range_update(l, r, k, 0, 0)
        elif q == 4:
            lst.range_update(l, r, 1, 0, k)

if __name__ == '__main__':
    main()
0