반응형
https://www.acmicpc.net/problem/14428
14428번: 수열과 쿼리 16
길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i v : Ai를 v로 바꾼다. (1 ≤ i ≤ N, 1 ≤ v ≤ 109) 2 i j : Ai, Ai+1, ..., Aj에서 크기가 가장 작은 값의
www.acmicpc.net
[ 문제풀이 ]
이 문제를 풀기 전에 다음 글을 읽고 오시면 좋습니다!!
https://rudalsd.tistory.com/51?category=1073064
[ 자료구조 ] 세그먼트 트리 (Segment Tree)
1. 세그먼트 트리 (Segment Tree) 먼저, 세그먼트 트리가 무엇인지 알아봅시다! 세그먼트 트리는 구간 합을 저장하기 위한 트리입니다. 예를 들어 size가 5인 배열이 있다고 생각해봅시다. int arr [5] = {1
rudalsd.tistory.com
이 문제는 가장 작은 수의 인덱스를 출력해야 하는 문제이기 때문에 node struct를 만들어서 숫자와 인덱스를 저장합니다. 나머지는 다른 세그먼트 트리와 같은 방식으로 풀어주면 됩니다.
[ 소스 코드 ]
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #include<iostream> #include<vector> #include<cmath> using namespace std; struct node { int num; int idx; }; int N, M; int arr[100001]; vector<node> segTree; node makeTree(int cur, int start, int end) //세그먼트 트리 만들기 { int mid = (start + end) / 2; if (start == end) { return segTree[cur] = { arr[start], start }; } node left = makeTree(cur * 2, start, mid); //왼쪽 자식 노드 node right = makeTree(cur * 2 + 1, mid + 1, end); //오른쪽 자식 노드 if (left.num < right.num) { return segTree[cur] = { left.num, left.idx }; } else if (right.num < left.num) { return segTree[cur] = { right.num, right.idx }; } else { if (left.idx < right.idx) { return segTree[cur] = { left.num, left.idx }; } else { return segTree[cur] = { right.num, right.idx }; } } } node updateTree(int cur, int start, int end, int idx) //세그먼트 트리 업데이트 { if (idx < start || idx > end) { //start ~ end에 idx가 포함되어 있지 않을 때 return segTree[cur]; } if (start == end) { //바꿀 숫자의 idx에 도착했을 때 return segTree[cur] = { arr[start], start }; } int mid = (start + end) / 2; node left = updateTree(cur * 2, start, mid, idx); //왼쪽 자식 노드 node right = updateTree(cur * 2 + 1, mid + 1, end, idx); //오른쪽 자식 노드 if (left.num < right.num) { return segTree[cur] = { left.num, left.idx }; } else if (right.num < left.num) { return segTree[cur] = { right.num, right.idx }; } else { if (left.idx < right.idx) { return segTree[cur] = { left.num, left.idx }; } else { return segTree[cur] = { right.num, right.idx }; } } } node minTree(int cur, int start, int end, int sidx, int eidx) //최솟값 구하기 { if (end < sidx || start > eidx) { //범위를 완전히 벗어났을 때 return { 1111111111, 987654321 }; } if (sidx <= start && eidx >= end) { //범위에 완전히 포함될 때 return segTree[cur]; } //범위에 일부 포함될 때 int mid = (start + end) / 2; node left = minTree(cur * 2, start, mid, sidx, eidx); node right = minTree(cur * 2 + 1, mid + 1, end, sidx, eidx); if (left.num < right.num) { return left; } else if (right.num < left.num) { return right; } else { if (left.idx < right.idx) { return left; } else { return right; } } } int main() { cin >> N; for (int i = 1; i <= N; i++) { scanf("%d", &arr[i]); } int size = (1 << (int)(ceil(log2(N) + 1))); segTree.resize(size); makeTree(1, 1, N); cin >> M; for (int i = 0; i < M; i++) { int a, b, c; scanf("%d %d %d", &a, &b, &c); if (a == 1) { arr[b] = c; updateTree(1, 1, N, b); } else { node ans = minTree(1, 1, N, b, c); printf("%d\n", ans.idx); } } } | cs |
반응형
'백준' 카테고리의 다른 글
[ 백준 ] 1086번 - 박성원 (C++) (0) | 2022.07.15 |
---|---|
[ 백준 ] 17371번 - 이사 (C++) (0) | 2022.07.14 |
[ 백준 ] 13977번 - 이항 계수와 쿼리 (C++) (0) | 2022.07.12 |
[ 백준 ] 11689번 - GCD(n, k) = 1 (C++) (0) | 2022.07.11 |
[ 백준 ] 3015번 - 오아시스 재결합 (C++) (0) | 2022.07.10 |