結果

問題 No.3507 RangeSum RangeUpdate RangeSqrt
コンテスト
ユーザー rumblycascade7
提出日時 2026-04-18 06:00:24
言語 Python3
(3.14.3 + numpy 2.4.4 + scipy 1.17.1)
コンパイル:
python3 -mpy_compile _filename_
実行:
python3 _filename_
結果
TLE  
実行時間 -
コード長 4,037 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 558 ms
コンパイル使用メモリ 20,832 KB
実行使用メモリ 42,520 KB
最終ジャッジ日時 2026-04-18 06:01:08
合計ジャッジ時間 10,891 ms
ジャッジサーバーID
(参考情報)
judge2_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other AC * 1 TLE * 2 -- * 26
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

import sys
import math

input = sys.stdin.readline


class SegTree:
    def __init__(self, a):
        sz = 1
        while sz < len(a):
            sz <<= 1
        self.sz = sz

        m = sz << 1
        self.sm = [0] * m
        self.mn = [0] * m
        self.mx = [0] * m

        self.lz_set = [None] * m
        self.lz_add = [0] * m

        for i in range(sz):
            if i < len(a):
                val = a[i]
            else:
                val = 0

            p = sz + i
            self.sm[p] = val
            self.mn[p] = val
            self.mx[p] = val

        for i in range(sz - 1, 0, -1):
            self.pull(i)

    def pull(self, i):
        lc = i << 1
        rc = lc | 1
        self.sm[i] = self.sm[lc] + self.sm[rc]
        self.mn[i] = min(self.mn[lc], self.mn[rc])
        self.mx[i] = max(self.mx[lc], self.mx[rc])

    def apply_set(self, i, l, r, v):
        self.sm[i] = v * (r - l)
        self.mn[i] = v
        self.mx[i] = v
        self.lz_set[i] = v
        self.lz_add[i] = 0

    def apply_add(self, i, l, r, d):
        if d == 0:
            return

        self.sm[i] += d * (r - l)
        self.mn[i] += d
        self.mx[i] += d

        if self.lz_set[i] is not None:
            self.lz_set[i] += d
        else:
            self.lz_add[i] += d

    def push(self, i, l, r):
        if r - l == 1:
            self.lz_set[i] = None
            self.lz_add[i] = 0
            return

        mid = (l + r) >> 1
        lc = i << 1
        rc = lc | 1

        if self.lz_set[i] is not None:
            v = self.lz_set[i]
            self.apply_set(lc, l, mid, v)
            self.apply_set(rc, mid, r, v)
            self.lz_set[i] = None

        if self.lz_add[i] != 0:
            d = self.lz_add[i]
            self.apply_add(lc, l, mid, d)
            self.apply_add(rc, mid, r, d)
            self.lz_add[i] = 0

    def update_set(self, ql, qr, v, i=1, l=0, r=None):
        if r is None:
            r = self.sz

        if qr <= l or r <= ql:
            return

        if ql <= l and r <= qr:
            self.apply_set(i, l, r, v)
            return

        self.push(i, l, r)
        mid = (l + r) >> 1

        self.update_set(ql, qr, v, i << 1, l, mid)
        self.update_set(ql, qr, v, i << 1 | 1, mid, r)

        self.pull(i)

    def query_sum(self, ql, qr, i=1, l=0, r=None):
        if r is None:
            r = self.sz

        if qr <= l or r <= ql:
            return 0

        if ql <= l and r <= qr:
            return self.sm[i]

        self.push(i, l, r)
        mid = (l + r) >> 1

        left_sum = self.query_sum(ql, qr, i << 1, l, mid)
        right_sum = self.query_sum(ql, qr, i << 1 | 1, mid, r)

        return left_sum + right_sum

    def update_sqrt(self, ql, qr, i=1, l=0, r=None):
        if r is None:
            r = self.sz

        if qr <= l or r <= ql:
            return

        if self.mx[i] <= 1:
            return

        if ql <= l and r <= qr:
            d1 = math.isqrt(self.mn[i]) - self.mn[i]
            d2 = math.isqrt(self.mx[i]) - self.mx[i]

            if d1 == d2:
                self.apply_add(i, l, r, d1)
                return

        if r - l == 1:
            nv = math.isqrt(self.mx[i])
            self.apply_set(i, l, r, nv)
            return

        self.push(i, l, r)
        mid = (l + r) >> 1

        self.update_sqrt(ql, qr, i << 1, l, mid)
        self.update_sqrt(ql, qr, i << 1 | 1, mid, r)

        self.pull(i)


def main():
    n, q = map(int, input().split())
    a = list(map(int, input().split()))

    seg = SegTree(a)
    ans = []

    for _ in range(q):
        qry = list(map(int, input().split()))
        t = qry[0]

        if t == 0:
            l, r = qry[1], qry[2]
            ans.append(str(seg.query_sum(l, r)))

        elif t == 1:
            l, r, x = qry[1], qry[2], qry[3]
            seg.update_set(l, r, x)

        else:
            l, r = qry[1], qry[2]
            seg.update_sqrt(l, r)

    print("\n".join(ans))


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