sqrt decomposition: O(√N) 갱신 + O(√N) 쿼리. 구현은 seg tree 의 절반.
핵심 통찰: 블록 단위로 묶어 precompute 하면, partial 블록만 순회하고 full 블록은 블록 값으로 O(1) 처리.
시각화
핵심 아이디어
invariant: 블록 크기 B = √N. 각 블록의 합을 block_sum[k] 에 저장.
block_sum[k] = sum of a[k*B .. min((k+1)*B-1, N-1)]range_add(l, r, x): for i in l..r: if i % B == 0 and i + B - 1 <= r: # full block block_sum[i/B] += x * B i += B else: a[i] += x block_sum[i/B] += x
알고리즘
B = int(sqrt(N)) + 1block_cnt = (N + B - 1) / B// 전처리for k in 0..block_cnt-1: block_sum[k] = sum of a[k*B .. min((k+1)*B-1, N-1)]// 구간 합 쿼리range_sum(l, r): res = 0 while l <= r: if l % B == 0 and l + B - 1 <= r: res += block_sum[l / B] l += B else: res += a[l] l += 1 return res// 점 갱신point_update(pos, val): block_sum[pos / B] += val - a[pos] a[pos] = val
구현
// Sqrt decomposition, range sum + point update#include <bits/stdc++.h>using namespace std;int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, q; cin >> n >> q; vector<long long> a(n); for (auto& v : a) cin >> v; int B = (int)sqrt(n) + 1; int bc = (n + B - 1) / B; vector<long long> block(bc, 0); for (int i = 0; i < n; i++) block[i / B] += a[i]; while (q--) { int t; cin >> t; if (t == 1) { int l, r; cin >> l >> r; l--; r--; long long res = 0; while (l <= r) { if (l % B == 0 && l + B - 1 <= r) { res += block[l / B]; l += B; } else { res += a[l]; l++; } } cout << res << "\n"; } else { int pos, val; cin >> pos >> val; pos--; block[pos / B] += val - a[pos]; a[pos] = val; } }}
import sys, mathinput = sys.stdin.readlinen, q = map(int, input().split())a = list(map(int, input().split()))B = int(math.sqrt(n)) + 1bc = (n + B - 1) // Bblock = [0] * bcfor i in range(n): block[i // B] += a[i]out = []for _ in range(q): t, *rest = map(int, input().split()) if t == 1: l, r = rest; l -= 1; r -= 1 res = 0 while l <= r: if l % B == 0 and l + B - 1 <= r: res += block[l // B] l += B else: res += a[l] l += 1 out.append(str(res)) else: pos, val = rest; pos -= 1 block[pos // B] += val - a[pos] a[pos] = valprint("\n".join(out))
stdin
5 41 2 3 4 51 1 32 3 101 1 31 1 5
결과
61322
복잡도
항목
값
시간 (전처리)
O(N)
시간 (쿼리)
O(√N)
시간 (갱신)
O(1)
공간
O(N)
안정성
N/A
변형 / 활용
변형
설명
Range add + range sum
block 에 lazy tag 저장. full block 은 tag, partial 은 brute.
💬 댓글