정의

게으르게 전파하여 갱신하는 자료구조이다.

  • 기존 세그먼트 트리는 갱신을 즉시 처리 했지만, Lazy를 이용하여 필요할 때 한꺼번에 처리한다.
  • 특정 구간 [a, b]에 값 c를 동시에 연산할 때 사용된다
  • 단순한 세그먼트 트리로 특정 구간의 길이 N을 연산 한다면 O(NlogN)가 걸리지만 O(logN)로 줄일 수 있다

 

예시 코드

세그먼트 트리 + Lazy propagation

  • 세그먼트 트리는 완전 이진트리가 아닐 수 있음
  • 그러므로 propagate 함수 안에 현재 노드가 자식인지를 확인하는 if(l != r)가 if(node < si)로 대체될 수 없음
// 백준 10999번 구간 합 구하기2

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int si = 1;
ll arr[1024*1024];
ll seg[1024*1024*2], lazy[1024*1024*2];

// 세그먼트 트리 초기화
long long init(int l, int r, int node){
	if(l == r) return seg[node] = arr[l];
	
	int mid = (l+r)/2;
	return seg[node] = init(l, mid, node*2) + init(mid+1, r, node*2+1);
}

// Lazy Propagate
void propagate(int l, int r, int node){
    if(lazy[node] == 0) return;
    
    if(l != r){
        lazy[node*2] += lazy[node];
        lazy[node*2+1] += lazy[node];
    }
    seg[node] += lazy[node] * (r-l+1);
    lazy[node] = 0;
}

// 구간의 값 변경
void update(int l, int r, int node, int st, int en, ll n) {
    propagate(l, r, node);

    if(en < l || r < st) return;
    if(st <= l && r <= en) {
        lazy[node] += n;
        propagate(l, r, node);
        return;
    }

    int mid = (l+r)/2;

    update(l, mid ,node*2, st, en ,n);
    update(mid+1, r, node*2+1, st, en, n);

    seg[node] = seg[node*2] + seg[node*2+1];
}

// 구간의 합 구하기
ll sum(int l, int r, int node, int st, int en) {
    propagate(l, r, node);
    
    if(en < l || r < st) return 0;
    if(st <= l && r <= en) return seg[node];
    
    int mid = (l+r)/2;

    return sum(l, mid, node*2, st, en) + sum(mid+1, r, node*2+1, st, en);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(NULL);

    int n, m, k;

    cin >> n >> m >> k;

    while(si < n) si <<= 1;

    for(int i = 0; i < n; i++) 
        cin >> arr[i];

    init(0, n-1, 1);
  
    ll a,b,c,d;
    for(int i = 0; i < m+k; i++) {
        cin >> a >> b >> c;
        if(a == 1) {
            cin >> d;
            update(0, n-1, 1, b-1, c-1, d);
        }
        else
            cout << sum(0, n-1, 1, b-1, c-1) << '\n';
    }

    return 0;
}

같이 보면 좋을 글