구간 합 구하기 문제는 전형적인 세그먼트 트리를 이용하여 푸는 문제입니다. 세그먼트 트리 이외에도 비슷한 방식들이 존재합니다.
세그먼트 트리를 이용하는 문제는,
1. 많은 수의 쿼리를 진행해야 하고,
2. 미리 연산한 결과를 사용할 수 있어야 하고,
3. 미리 연산한 결과를 수정해야할 경우가 많은 경우
형태일겁니다.
위의 조건이 만족하지 않는다면, 다른 방식으로 계산하는 것이 더 좋을 수 있습니다.
세그먼트 트리와 관련한 문제들은 다음과 같습니다.
백준 #1849 순열(세그먼트 트리)
이번 문제는 N개의 배열에 1부터 N까지 한번씩만 숫자가 써져있는 a[i] 수열이 있을경우, A[i] 란 수열은 원래의 수열에서 i번째 수의 앞에 있는 수 중 i보다 큰 값이 있는 개수가 됩니다. 예를 들어
sdev.tistory.com
#1395 스위치(Segment Tree)
이번 문제는 Platinum III 난이도로 매겨진 좀 난이도가 있는 문제입니다. 기본적으로 이용하는 자료구조는 세그먼트 트리입니다. 세그먼트 트리 자료구조는 제가 나중에 한번 알고리즘적 적용 방
sdev.tistory.com
백준 #1275 커피숍2
이번 문제는 난이도는 Platinum V로 되어 있습니다. 백준 알고리즘 문제들 중 어려운 문제들의 유형이 몇가지가 있는데, 이 문제는 그 중 세그먼트 트리 등 이진트리의 변형을 이용하고 있습니다.
sdev.tistory.com
세그먼트 트리는

다음은 제가 작성한 소스입니다.
//------------------------------------------------
// baekjoon #2042
// - by Aubrey Choi
// - created at 2019-08-04
//------------------------------------------------
#include <stdio.h>
// Segment tree
template<class T> class SegmentTree
{
public:
SegmentTree(int n) { int s=1; while(s<n) s<<=1; tree = new T[s<<1]; v = new T[n]; }
~SegmentTree() { delete[] tree; delete[] v; }
T init(int c, int s, int e)
{
if(s+1==e) return tree[c]=v[s];
int m = (s+e)/2;
return tree[c]=init(c*2, s, m)+init(c*2+1, m, e);
}
void update(int c, int s, int e, int idx, T diff)
{
if(idx<s||idx>=e) return;
tree[c]+=diff;
if(s+1==e) return;
int m = (s+e)/2;
update(c*2, s, m, idx, diff);
update(c*2+1, m, e, idx, diff);
}
int find(int c, int s, int e, T sum)
{
if(s+1==e) return s;
int m = (s+e)/2;
if(tree[c*2]>=sum) return find(c*2, s, m, sum);
return find(c*2+1, m, e, sum-tree[c*2]);
}
T sum(int c, int s, int e, int sc, int ec)
{
if(ec<=s||sc>=e) return 0; if(sc<=s&&ec>=e) return tree[c];
int m = (s+e)/2;
return sum(c*2,s,m,sc,ec)+sum(c*2+1,m,e,sc,ec);
}
T operator [](const int i) { return v[i]; }
T *getTree() { return tree+1; }
T *getValue() { return v; }
private:
T *tree, *v;
};
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k); m+=k;
SegmentTree<long long> tree(n);
long long *data = tree.getValue();
for(int i=0;i<n;i++) scanf("%lld",data+i);
tree.init(1,0,n);
while(m--)
{
int a, b; long long c;
scanf("%d%d%lld", &a, &b, &c);
if(a==1) { c-=data[b-1]; data[b-1]+=c; tree.update(1, 0, n, b-1, c); }
else printf("%lld\n", tree.sum(1, 0, n, b-1, (int)c));
}
return 0;
}
'Programming > BOJ' 카테고리의 다른 글
[C/C++] 백준 #2075 N번째 큰 수(n'th element) (0) | 2023.03.25 |
---|---|
[C/C++] 백준 #2056 작업(위상정렬) (0) | 2023.03.23 |
[C/C++] 백준 #2023 신기한 소수(수학) (0) | 2023.01.19 |
[C/C++] 백준 #2014 소수의 곱(우선 순위 큐) (0) | 2023.01.17 |
[C/C++] 백준 #2011 암호코드(동적 계획법) (0) | 2023.01.15 |
댓글