알고리즘 문제/백준

11505 구간 곱 구하기 (세그먼트 트리) [Gold I]

우대비 2024. 4. 24. 10:51
반응형
 

11505번: 구간 곱 구하기

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

www.acmicpc.net

 

세그먼트 트리

세그먼트 트리(Segment Tree) 구간 쿼리와 수정이 빈번하게 일어나는 상황에서 유용하게 사용할 수 있는 자료구조입니다. 배열의 특정 구간에 대한 정보를 빠르게 구하거나 업데이트할 때 사용되며

flrjtwjrjt.tistory.com

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

vector<long> tree;
static int MOD = 1000000007;
void SetTree(int i);
long GetMul(int s, int e);
void ChangeValue(int index, long value);

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

	int N, M, K;
	cin >> N >> M >> K;

	int treeHeight = 0;
	int Length = N;

	while (Length > 0)
	{
		Length /= 2;
		treeHeight++;
	}
	 
	int treeSize = int(pow(2, treeHeight + 1));
	int startNodeId = treeSize / 2 - 1;
	tree.resize(treeSize + 1);  
	fill(tree.begin(), tree.end(), 1);

	for (int i = startNodeId + 1; i <= startNodeId + N; i++)
	{
		cin >> tree[i];
	}
	SetTree(treeSize - 1);

	for (int i = 0; i < M + K; i++)
	{
		long a, b, c;
		cin >> a >> b >> c;
		if (a == 1) {
			ChangeValue(b + startNodeId, c); 
		}
		else if (a == 2)
			cout << GetMul(b + startNodeId, c + startNodeId) << "\n";

	}
	 
}
  
void ChangeValue(int index, long value)
{
	tree[index] = value;
	 
	while (index > 1) { 
		index =  index / 2;
		tree[index] = tree[index * 2] % MOD * tree[index * 2 + 1] % MOD; 
	}
}

long GetMul(int s, int e)
{
	long result = 1;
	 
	while (s <= e)
	{
		if (s % 2 == 1) {
			result = result * tree[s] % MOD;
			s++;
		}
		if (e % 2 == 0) {   
			result = result *  tree[e] % MOD;
			e--;
		}
		 
		s /= 2; 
		e /= 2; 
	}

	return result; 
}

void SetTree(int index)
{ 
	while (index != 1)
	{
		tree[index / 2] = tree[index / 2] * tree[index] % MOD;
	
		index--; 
	}
}
반응형
LIST