문제: icpc.me/2042
값의 갱신이 빈번하게 일어 날 때 구간 합을 구하는 문제이다.
구간에 대한 합은 파셜섬을 이용한다면 O(N)에 해결할 수 있지만 값의 갱신이 빈번하게 일어 난다면 갱신이 일어 날 때 마다 O(N)의 시간이 걸리므로 총 O(N*M)의 시간복잡도를 가지게 될 것이다.
문제에서 N이 100만 M이 만이므로 시간을 초과할 것이다.
따라서 문제를 해결하기 위하여 세그먼트 트리를 이용하여 갱신과 구간 합 출력을 O(logN)에 해결해줘서 O((M+K)logN)의 시간에 문제를 해결 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; ll n, m, k, x, y, z; ll seg[4000000]; ll update(ll pos, ll val, ll node, ll x, ll y) { if (pos < x || y < pos) return seg[node]; if (x == y) return seg[node] = val; ll mid = (x + y) >> 1; return seg[node] = update(pos, val, node * 2, x, mid) + update(pos, val, node * 2 + 1, mid + 1, y); } ll query(ll lo, ll hi, ll node, ll x, ll y) { if (y < lo || hi < x) return 0; if (lo <= x&&y <= hi) return seg[node]; ll mid = (x + y) >> 1; return query(lo, hi, node * 2, x, mid) + query(lo, hi, node * 2 + 1, mid + 1, y); } int main() { scanf("%lld%lld%lld", &n, &m, &k); for (int i = 1; i <= n; i++) { scanf("%lld", &x); update(i, x, 1, 1, n); } for (int i = 0; i < m + k; i++) { scanf("%lld%lld%lld", &x, &y, &z); if (x == 1) update(y, z, 1, 1, n); else printf("%lld\n", query(y, z, 1, 1, n)); } return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)10868 최소값 (0) | 2017.01.10 |
---|---|
BOJ)2357 최소값과 최대값 (1) | 2017.01.10 |
BOJ)1654 랜선 자르기 (0) | 2017.01.06 |
BOJ)4627 뛰어라 도마뱀 (0) | 2017.01.06 |
BOJ)13701 중복 제거 (0) | 2017.01.06 |