티스토리 뷰

#include <stdio.h>
typedef long long int L;
//Fenwick tree : 범위 수정, 단일 질문에 주로 사용합니다.
L arr[100001] = {}, tree[100001] = {}; //arr은 요소를 담는, tree는 말그대로 tree
int n, m;

void update(int i, int x) { //요소가 갱신된 후 tree을 갱신할 때 사용합니다.
	while(i<=n) {
		tree[i] += x;
		i += i & (-i);
	}
}

L sum(int i) { //단일 요소의 크기를, 요소들간의 차를 이용하여 구합니다.
	L ans = 0;
	while(i) {
		ans += tree[i];
		i -= i & (-i);
	} return ans;
}


int main(void)
{
	scanf("%d", &n);
	for(int i=1; i<=n; i++) { //인덱스는 1부터 시작합니다.
		scanf("%lld", &arr[i]); //요소들을 입력 받습니다.
		update(i, arr[i]-arr[i-1]); //트리들은 요소들의 차로 구성됩니다.
	} //arr[0]은 0으로 두었습니다.
	
	scanf("%d", &m);
	while(m--) {
		int a, b, c, d;
		scanf("%d", &a);
		if(a==1) { //범위 수정
			scanf("%d %d %d", &b, &c, &d);
			update(b, d);
			update(c+1, -d);
		}
		else { //단일 질문
			scanf("%d", &b);
			printf("%lld\n", sum(b));
		}
	}
}

풀이 : Fenwick tree 사용

 

여러개의 값을 수정 할 때, 범위내의 요소를 전부 다 더해주면, 시간이 매우 많이 걸리게 됩니다 (범위가 커질수록)

그러므로, 각 요소간의 차이를 이용해야 합니다.

 

1 2 3 4 5 가 있을 때 이것을 차이로 보면

1 1 1 1 1 (인덱스 0의 요소는 0으로 보았을 때 입니다) 입니다.

 

여기서 1 2 3 4 5 에서 2번째 부터 4번째 까지 100을 더해준다면, 일일이 더해 줄 필요 없이

1 101 1 1 -99 가 됩니다. 즉 구간의 시작지점에는 더해줄 값을 더해주고 마지막지점 이후에 더해줄 값을 빼주면 됩니다.

 

단일 요소의 값을 구할 때는 요소 인덱스 1부터 구하는 값의 요소 인덱스까지의 요소끼리의 차이를 더하면, 알 수 있게 됩니다.

 

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

 

16975번: 수열과 쿼리 21

길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i j k: Ai, Ai+1, ..., Aj에 k를 더한다. 2 x: Ax 를 출력한다.

www.acmicpc.net

 

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함