https://www.acmicpc.net/problem/11505
해당 문제는 수열의 특정 구간 곱을 구하는 문제로, 세그먼트 트리 알고리즘을 사용하여 풀이했다.
1) 수열을 저장할 datas
, 구간합 트리를 저장할 tree
배열을 선언한다. 이 때 구간합 트리의 크기는 수열 배열의 최대 크기의 4배 이상으로 설정한다.
2) 수의 개수 n
과 수의 변경이 일어나는 횟수 m
, 구간 곱을 구하는 횟수 k
를 입력 받아 저장하고, n개의 수를 입력받아 datas
에 저장한다.
3) init()
함수를 통해 구간합 트리를 초기화 한다.
4) m + k
만큼의 (곱 구하기, 수 바꾸기)를 실행한다.
mul()
함수를 통해 현재 순서에서 구해야하는 범위의 구간합을 구하고 이를 출력한다.mul()
을 실행한다.update()
함수를 통해 특정 인덱스의 수를 다른 수로 변경한다.init()
과 같이 하위 노드 값부터 상위 노드로 바뀌는 방식으로 진행한다.dif
)를 현재 순서 노드의 값으로 설정하고 반환한다.update()
를 실행한다.update()
함수 실행 이후 datas
의 특정 인덱스 값도 변경해주어야 한다.#include <iostream>
#include <algorithm>
using namespace std;
int n, m, k;
long long tree[4000004];
long long datas[1000001];
const long long MOD = 1000000007;
// 구간곱 트리 초기화
long long init(int start, int end, int node)
{
if (start == end) return tree[node] = datas[start];
int mid = start + (end - start) / 2;
return tree[node] = (init(start, mid, node * 2) * init(mid + 1, end, node * 2 + 1)) % MOD;
}
// 구간곱 구하기
long long mul(int start, int end, int node, int left, int right)
{
if (end < left || right < start) return 1;
if (left <= start && end <= right) return tree[node];
int mid = start + (end - start) / 2;
return (mul(start, mid, node * 2, left, right)
* mul(mid + 1, end, node * 2 + 1, left, right)) % MOD;
}
// 특정 수 변경
long long update(int start, int end, int node, int index, long long dif)
{
if (index < start || end < index) return tree[node];
if (start == end) return tree[node] = dif; // index가 현재 구간에 들어오고, 구간 내에 수가 하나 뿐이다 -> 해당 수가 바꾸고자 하는 수이므로 해당 노드 값 변경
int mid = start + (end - start) / 2;
return tree[node] = (update(start, mid, node * 2, index, dif) * update(mid + 1, end, node * 2 + 1, index, dif)) % MOD;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
cin >> datas[i];
init(1, n, 1);
for (int i = 0; i < m + k; i++)
{
int a, b, c;
cin >> a >> b >> c;
if (a == 1)
{
update(1, n, 1, b, c);
datas[b] = c;
}
else
cout << mul(1, n, 1, b, c) << '\n';
}
}