반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. 세그먼트 트리(Segment Tree) :: http://www.crocus.co.kr/648

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
#include <iostream>
#include <cstdio>
#include <vector>
#include <math.h>
 
#define MOD 1000000007
 
using namespace std;
 
typedef long long ll;
 
ll val;
 
ll init(vector<ll> &arr, vector<ll> &tree, int node, int start, int end)
{
    // start == end면 리프 노드이다.
    if (start == end)
        return tree[node] = arr[start];
 
    // 각 노드의 자식 노드에서 타고 올라온 return 값을 곱해주어 자신의 노드에 값을 넣는다.
    else
        return tree[node] = ((init(arr, tree, node * 2, start, (start + end) / 2) % MOD) * (init(arr, tree, node * + 1, (start + end) / + 1, end) % MOD)) % MOD;
}
 
ll update(vector<ll> &tree, int node, int start, int end, int index)
{
    // start와 end 구간 사이에 index가 아니면 갱신없이 현재 노드를 반환해준다. 
    if (!(start <= index && index <= end))
        return tree[node];
 
    // 리프 노드 업데이트
    if (start == end)
        return tree[node] = val;
 
    return tree[node] = (update(tree, node * 2, start, (start + end) / 2, index) * update(tree, node * + 1, (start + end) / + 1, end, index))%MOD;
}
 
ll mul(vector<ll> &tree, int node, int start, int end, int left, int right)
{
    // 현재 구하고자 하는 범위의 값이 아닌경우 구간 곱이기에 1을 return
    if (left > end || right < start)
        return 1;
 
    // left와 right가 start와 end를 포함하는 경우 현재 노드를 반환
    if (left <= start && end <= right)
        return tree[node];
 
    return ( mul(tree, node * 2, start, (start + end) / 2, left, right) * mul(tree, node * + 1, (start + end) / + 1, end, left, right) )% MOD;
}
int main()
{
    int n, m, k;
    scanf("%d %d %d"&n, &m, &k);
 
    int h = (int)ceil(log2(n));
    int tree_size = (<< (h + 1));
 
    vector<ll> arr(n);
    vector<ll> tree(tree_size);
 
    for (int i = 0; i < n; i++)
 
        scanf("%lld"&arr[i]);
 
    init(arr, tree, 10, n - 1);
 
    m += k;
 
    while (m--)
    {
        int get;
        scanf("%d"&get);
 
        // 구간을 갱신
        if (get == 1)
        {
            int pos;
 
            scanf("%d %lld"&pos, &val);
            update(tree, 10, n - 1, pos - 1);
        }
 
        // 구간 곱을 출력
        else if (get == 2)
        {
            int left, right;
            scanf("%d %d"&left, &right);
            printf("%lld\n", mul(tree, 10, n - 1, left - 1, right - 1)%MOD);
        }
    }
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
 
Crocus


반응형

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

[12837번] 가계부 (Hard)  (0) 2017.03.13
[2357번] 최소값과 최대값  (0) 2017.03.13
[2042번] 구간 합 구하기  (0) 2017.03.08
[2251번] 물통  (0) 2017.03.06
[1149번] RGB거리  (0) 2017.03.06