Henu
개발냥발
Henu
전체 방문자
오늘
어제
  • 분류 전체보기 (411)
    • DevOps (52)
      • Kubernetes (19)
      • Docker (14)
      • AWS (3)
      • Nginx (4)
      • Linux (4)
      • ArgoCD (1)
      • CN (2)
      • NATS (0)
      • Git (5)
    • Back-End (30)
      • Django (18)
      • Spring (5)
      • JPA (1)
      • MSA (5)
    • CS (87)
      • SystemSoftware (20)
      • OS (25)
      • Computer Architecture (16)
      • Network (23)
      • Database (2)
    • Lang (21)
      • Java (9)
      • Python (4)
      • C# (8)
    • Life (12)
    • 블록체인 (2)
    • Algorithm (204)
      • BOJ (160)
      • 프로그래머스 (19)
      • LeetCode (4)
      • SWEA (1)
      • 알고리즘 문제 해결 전략 (8)
      • DS, algorithms (7)
      • Checkio (5)
    • IT (2)

블로그 메뉴

  • GitHub
  • 글쓰기
  • 관리자

공지사항

  • Free!

인기 글

태그

  • Kubernetes
  • BFS
  • 백트래킹
  • django
  • boj
  • docker
  • Network
  • 다이나믹 프로그래밍
  • 프로그래머스
  • DFS

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Henu

개발냥발

[백준 10999] 구간 합 구하기 2 (C++)
Algorithm/BOJ

[백준 10999] 구간 합 구하기 2 (C++)

2021. 7. 31. 17:42
 

10999번: 구간 합 구하기 2

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 횟수이고, K는 구간의 합을 구하는 횟수이다. 그리고 둘째 줄부터 N+1번째 줄

www.acmicpc.net

세그먼트 트리, Lazy propagation


처음에 그냥 세그먼트 트리를 사용했다.

구간을 update할 때마다 리프노드까지 들어가서 update하고, 되돌아오면서 update값을 더해서 tree에 적용해줬다.

 

제출하면서도 매우 찝찝했다. 값을 수정하는 구간이 1~N까지라면 값을 update하는데 N의 시간이 걸리게 될 것이다..

구간합을 찾는 쿼리는 log(N)이라서 둘을 더하면 O(NM + Klog(N))이 되어 NM때문에 시간초과가 날거같았고 당연히 TLEㅠ

 

알고리즘 분류를 먼저 보니까 느리게 갱신되는 세그먼트 트리 라고 하는 분류가 있었다.

Lazy segment tree 를 어렴풋이 들은적이있어서 구글에서 배우기 위해 검색했다.

 

블로그 3개쯤 보면서 대충 감을 잡아가는 중에 아래 글을 우연히 봤다!

 

세그먼트 트리 나중에 업데이트 해야지!

배열 A가 있고, 여기서 다음과 같은 두 연산을 수행해야하는 문제가 있습니다. 10999번 문제: 구간 합 구하기 2 구간 l, r (l ≤ r)이 주어졌을 때, A[l] + A[l+1] + ... + A[r-1] + A[r]을 구해서 출력하기 i번째

www.acmicpc.net

 

lazy segment tree에 대해서 완벽히 설명된 글인듯 하다. 바로 이해할 수 있었고 코드까지 나와있어서 아주 편하게 이해했다.

어서 응용문제를 풀고싶다!

 

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#define fasti ios_base::sync_with_stdio(false); cin.tie(0);
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 1e9+7
#define pii pair<int, int>
#define MAX 1000001
typedef long long ll;
// typedef pair<int, int> pii;
 
using namespace std;
 
int N, M, K;
ll arr[MAX];
ll tree[MAX * 4];
ll lazy[MAX * 4];
 
void input(){
    cin >> N >> M >> K;
    for(int i = 1; i <= N; i++){
        cin >> arr[i];
    }
}
 
ll make_tree(int startidx, int endidx, int node){
    if(startidx == endidx) return tree[node] = arr[startidx];
    int mid = (startidx + endidx) / 2;
    return tree[node] = make_tree(startidx, mid, node*2) +\
                        make_tree(mid+1, endidx, node*2+1);
}
 
void update_lazy(int startidx, int endidx, int node){
    if(lazy[node]){
        tree[node] += (lazy[node] * (endidx - startidx +1));
        if(startidx != endidx){
            lazy[node*2] += lazy[node];
            lazy[node*2+1] += lazy[node];
        }
        lazy[node] = 0;
    }
}
 
ll getquery(int startidx, int endidx, int lidx, int ridx, int node){
    update_lazy(startidx, endidx, node);
    if(ridx < startidx || lidx > endidx) return 0;
    if(lidx <= startidx && endidx <= ridx) return tree[node];
    int mid = (startidx + endidx) / 2;
    return getquery(startidx, mid, lidx, ridx, node*2) + \
           getquery(mid+1, endidx, lidx, ridx, node*2+1);
}
 
void update(int startidx, int endidx, int lidx, int ridx, ll up, int node){
    // 미루다가 필요할 때 update한다
    update_lazy(startidx, endidx, node);
    if(ridx < startidx || lidx > endidx) return;
    if(lidx <= startidx && endidx <= ridx){
        tree[node] += (up * (endidx - startidx + 1));
        if(startidx != endidx){
            lazy[node*2] += up;
            lazy[node*2+1] += up;
        }
        return;
    }
    
    int mid = (startidx + endidx) / 2;
    update(startidx, mid, lidx, ridx, up, node*2);
    update(mid+1, endidx, lidx, ridx, up, node*2+1);
    tree[node] = tree[node*2] + tree[node*2+1];
}
 
void solve(){
    make_tree(1, N, 1);
    int a, b, c;
    ll d;
    for(int i = 0; i < K+M; i++){
        cin >> a;
        if(a & 1){
            cin >> b >> c >> d;
            update(1, N, b, c, d, 1);
        }
        else{
            cin >> b >> c;
            cout << getquery(1, N, b, c, 1) << "\n";
        }
    }
}
 
int main(){
    fastio
    input();
    solve();
    
    return 0;
}
 
Colored by Color Scripter
cs

 

'Algorithm > BOJ' 카테고리의 다른 글

[백준 11377] 열혈강호 3 (C++)  (0) 2021.08.02
[백준 2159] 케익 배달 (C++)  (0) 2021.08.01
[백준 1701] Cubeditor (C++)  (0) 2021.07.31
[백준 1275] 커피숍2 (C++)  (0) 2021.07.31
[백준 9019] DSLR (C++)  (0) 2021.07.30
    'Algorithm/BOJ' 카테고리의 다른 글
    • [백준 11377] 열혈강호 3 (C++)
    • [백준 2159] 케익 배달 (C++)
    • [백준 1701] Cubeditor (C++)
    • [백준 1275] 커피숍2 (C++)

    티스토리툴바