알고리즘 문제/백준

2024 구간 합 구하기 (세그먼트 트리) [Gold I]

우대비 2024. 4. 22. 11:57
반응형
 

2042번: 구간 합 구하기

첫째 줄에 수의 개수 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;

static vector<long> tree;
long getSum(int s, int e);
void changeVal(int index, long val);
void setTree(int i);

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 treeSize = 2;
	//for (int i = 1; i < treeHeight + 1; i++)  
	//	treeSize *= 2;

	int startNodeIndex = treeSize / 2 - 1;

	tree.resize(treeSize + 1);

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

	for (int i = 0; i < M + K; i++)
	{
		long a, s, e;
		cin >> a >> s >> e;

		if (a == 1) {
			changeVal(startNodeIndex + s, e);
		}
		else if (a == 2){
			cout << getSum(startNodeIndex + s, startNodeIndex + e) << "\n";
		}


	}
}
long getSum(int s, int e)
{
	long result = 0;

	while (s <= e)
	{
		if (s % 2 == 1) 
		{
			result += tree[s];
			s++;
		}
		if (e % 2 == 0)
		{
			result += tree[e];
			e--;
		}

		s /= 2;
		e /= 2; 
	}

	return result;

}

void changeVal(int s, long value)
{
	long diff = value - tree[s];
	 
	while (s > 0)
	{
		tree[s ] += diff;
		s /= 2;
	}
}


void setTree(int i)
{
	while (i != 1)
	{
		tree[i / 2] += tree[i];
		i--;
	}
}
반응형
LIST