반응형

문제 출처 :


https://www.acmicpc.net/problem/10999



알고리즘 분석 :


문제 해결에 필요한 사항

1. Segment Tree :: http://www.crocus.co.kr/648

2. Segment Tree with Lazy Propagation :: http://www.crocus.co.kr/658


2번 문제 해결 사항의 링크에 이 문제에 대한 설명을 수록해 두었습니다.







소스 코드 : 


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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
 
using namespace std;
 
typedef long long ll;
 
ll init(vector<ll> &arr, vector<ll> &tree, int node, int start, int end)
{
    if (start == end)
        return tree[node] = arr[start];
 
    int mid = (start + end) / 2;
 
    return tree[node] = init(arr, tree, node * 2, start, mid) + init(arr, tree, node * + 1, mid + 1, end);
}
 
void update_lazy(vector<ll> &tree, vector<ll> &lazy, int node, int start, int end)
{
    // lazy가 0이면 return;
    if (lazy[node] == 0)
        return;
    
    // 자식 노드가 있는 수 만큼 lazy값에 곱하여 더한다.
    // 자식에게 lazy를 분배하니 자식이 return으로 더해주지 못한 값을 직접 더한다.
    tree[node] += (end - start + 1* lazy[node];
 
    // leaf가 아니면
    // 자식에게 lazy를 물려준다.
    if (start != end)
    {
        lazy[node * 2+= lazy[node];
        lazy[node * + 1+= lazy[node];
    }
 
    // 물려준 후 lazy는 초기화
    lazy[node] = 0;
    
}
 
void update_range(vector<ll> &tree, vector<ll> &lazy, int node, int start, int end, int left, int right, ll val)
{
    /*
        순서 ::
        1. lazy가 존재하면 업데이트 해준다.(tree[node] 변화)
        2. val을 더해준다.(자식수가 있는 만큼)
        2에서 자식 수만큼 더해주는 이유는 자식들은 아직 lazy가 업데이트 되지 않았기 때문
    */
    // 현재 노드에 lazy가 있는지 확인 후, lazy가 있다면 node를 업데이트 해준다.
    update_lazy(tree, lazy, node, start, end);
 
    // 하나도 속하지 않는다면 return;
    if (left > end || right < start)
        return;
 
    // 원하는 구간 내에 있는 노드에 왔을 경우
    if (left <= start && end <= right)
    {
        // 자식 노드가 있는 수 만큼 val을 곱해서 더해준다.
        // 자식이 return으로 더해주는 형태가 아니니 직접 더한다.
        tree[node] += (end - start + 1* val;
 
        if (start != end)
        {
            lazy[node * 2+= val;
            lazy[node * + 1+= val;
        }
        return;
    }
 
    int mid = (start + end) / 2;
    update_range(tree, lazy, node * 2, start, mid, left, right, val);
    update_range(tree, lazy, node * + 1, mid + 1, end, left, right, val);
 
    // 구간이 걸쳐서 속해 있다면 자식 노드를 이용하여 부모 노드를 업데이트 한다.
    tree[node] = tree[node * 2+ tree[node * + 1];
}
 
ll sum(vector<ll> &tree, vector<ll> &lazy, int node, int start, int end, int left, int right)
{
    // update이후 남은 lazy를 해당하는 구간을 sum 할 때 업데이트 해준다.
    update_lazy(tree, lazy, node, start, end);
 
    if (left > end || right < start)
        return 0;
 
    if (left <= start && end <= right)
        return tree[node];
 
    int mid = (start + end) / 2;
    return sum(tree, lazy, node * 2, start, mid, left, right) + sum(tree, lazy, node * + 1, mid + 1, end, left, right);
}
 
int main()
{
    int n, m, k;
 
    scanf("%d %d %d"&n, &m, &k);
 
    int h = (int)ceil(log2(n));
    int tree_size = (<< (+ h));
 
    vector<ll> arr(n);
    vector<ll> tree(tree_size);
    vector<ll> lazy(tree_size);
 
    for (int i = 0; i < n; i++)
        scanf("%lld"&arr[i]);
 
    init(arr, tree, 10, n - 1);
    m += k;
 
    while (m--)
    {
        int num;
        scanf("%d"&num);
 
        if (num == 1)
        {
            int left, right;
            ll val;
 
            scanf("%d %d %lld"&left, &right, &val);
 
            update_range(tree, lazy, 10, n - 1, left-1, right-1, val);
        }
 
        else if (num == 2)
        {
            int left, right;
            scanf("%d %d"&left, &right);
 
            printf("%lld\n",sum(tree, lazy, 10, n - 1, left-1, right-1));
        }
    }
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[11437번] LCA  (0) 2017.03.15
[11438번] LCA 2  (0) 2017.03.15
[2661번] 좋은수열  (2) 2017.03.13
[1818번] 책정리  (0) 2017.03.13
[1965번] 상자넣기  (0) 2017.03.13