펜윅트리 - BOJ) 11658 구간합 구하기 3
11658 구간합 구하기 3을 풀려고 2d segment tree로 풀다가 시간초과나서 빡쳤다.
아마 initialization에서 시간초과가 뜨는 것 같은데 화가 난다. 좀 쉽게 코딩하려다가 봉변 당한것 같다.
각설하고 예전부터 펜윅 트리에 대해 본 적이 있는데 사실 그 날 공부하면 그 다음날 까먹는 그런 형태의 트리이다.
좋은 설명은 여기에 있다.
https://www.acmicpc.net/blog/view/21
위를 읽고 나름대로 정리를 해보면
${2^0, 2^1, 2^2, 2^3, ...}$와 같은 2의 제곱수를 생각해보자.
$tree[index]$에 대해 만약 $index$가 $k = argmax_{n} 2^n$로 나누어진다고 생각하면 해당 $tree[index]$ 는 k개의 원소를 갖는다. 심지어 $arr[index]$를 포함한 원소말이다.
즉 $arr[index-k+1], arr[index-k+2], ... ,arr[index]$의 원소의 sum을 $tree[index]$가 표현하고 잇는 것이다.
재밌는 것은 index를 이진수로 나타낼 때 11010와 같이 나타낼 수 있는데, 이 때 1이 나타나는 가장 끝의 위치를 이용하여 쉽게 sum과 update를 구할 수 있다.
index & -index 가 1이 나타나는 가장 끝의 위치를 말한다.
아래는 update와 sum에 대한 코드이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void update(int x, int y, int diff) { while(y <= N) { tree[x][y] += diff; y += (y & -y); } } int sum(int x, int y) { int ans = 0; while(y >= 1) { ans += tree[x][y]; y -= (y & -y); } return ans; } | cs |
댓글
댓글 쓰기