문제풀이/백준oj

[백준OJ] 2268번 수들의 합

Hyeon-Uk 2021. 5. 19. 22:41
반응형

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

 

2268번: 수들의 합

첫째 줄에는 N(1≤N≤1,000,000), M(1≤M≤1,000,000)이 주어진다. M은 수행한 명령의 개수이며 다음 M개의 줄에는 수행한 순서대로 함수의 목록이 주어진다. 첫 번째 숫자는 어느 함수를 사용했는지를

www.acmicpc.net


 

-풀이-

세그먼트트리의 기본적인 문제이다. 하지만 주의해야할점이 sum쿼리를 실행할때 i>j인 경우가 있으므로, 위와 같은 경우라면 i와 j를 swap해주어야한다.

또한 초기값이 모두 0이므로, 세그먼트트리를 초기화해주는 작업을 안해주어도 상관이없었다.

 

-시간복잡도-

sum과 modify 함수 모두 세그먼트트리의 쿼리이기 때문에 O(logN) 시간이 걸린다.

이 동작이 M번 반복되므로, O(MlogN)시간이 걸린다.

 

-코드-

 

#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;

ll tree[4 * 1000000];
ll arr[1000000];
int n,m;

ll init(int node, int st, int end) {
	if (st == end) {
		return tree[node] = arr[st];
	}

	int mid = (st + end) / 2;
	return init(node * 2, st, mid) + init(node * 2 + 1, mid + 1, end);
}

ll sum(int node, int st, int end, int left, int right) {
	if (left <= st && end <= right) {
		return tree[node];
	}
	if (right < st || end < left) {
		return 0;
	}

	int mid = (st + end) / 2;
	return sum(node * 2, st, mid, left, right) + sum(node * 2 + 1, mid + 1, end, left, right);
}

void modify(int node, int st, int end, int ind, long long dif) {
	if (ind < st || end < ind) return;
	tree[node] -= dif;
	
	if (st != end) {
		int mid = (st + end) / 2;
		modify(node * 2, st, mid, ind, dif);
		modify(node * 2 + 1, mid + 1, end, ind, dif);
	}
}

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

	cin >> n >> m;


	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		if (a == 0) {
			if (b > c) {
				int temp = b;
				b = c;
				c = temp;
			}
			cout << sum(1, 0, n - 1, b - 1, c - 1) << "\n";
		}
		else {
			long long diff = arr[b - 1] - c;
			arr[b - 1] = c;
			modify(1, 0, n - 1, b - 1, diff);
		}
	}
	return 0;
}
반응형