ํ”Œ๋ž˜ํ‹ฐ๋„˜5 : ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ ๋ฌธ์ œ์ด๋‹ค.

์ƒ๊ฐ

|0|1|2|3|4|5|6| |:|:|:|:|:|:|:| |4|1|7|5|2|9|8|

์ž…๋ ฅ๊ฐ’์ด ์ด๋ ‡๊ฒŒ ์ฃผ์–ด์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ์ด ์ƒํƒœ์—์„œ 3~6๊นŒ์ง€์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ฒƒ์€, ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ•ด๋„ ์œผ๋กœ ํ’€ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ํ™•์ธ(์ฟผ๋ฆฌ)๊ฐ€ ๋งŽ์•„์ง„๋‹ค๋ฉด, ๊ธ‰๊ฒฉํ•˜๊ฒŒ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ์˜ฌ๋ผ๊ฐ„๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๋ฌธ์ œ์—์„œ ์ œ์‹œํ•˜๋Š” m(100000) ๊ฐœ์— ๋Œ€ํ•ด์„œ n(100000)์„ ๋ชจ๋‘ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐ„๋‹ค๋ฉด ๋ฌธ์ œ๋ฅผ ํ’€ ์ˆ˜ ์—†๋‹ค.()

๋ฌธ์ œ์˜ ์›์ธ

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋Š ๋ถ€๋ถ„์—์„œ ์—ฐ์‚ฐ์ด ๋งŽ์ด ๊ฑธ๋ฆฌ๋Š” ์ง€ ์ƒ๊ฐํ•ด๋ณด์ž. ๊ฐ€์žฅ ํฐ ๋ถ€๋ถ„์„ ํŒ๋‹จ์„ ์ค‘๋ณต์œผ๋กœ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. 03๊นŒ์ง€์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ฒƒ๊ณผ, 14๊นŒ์ง€์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ณผ์ •์—๋Š” 1~3๊นŒ์ง€์˜ ์ตœ์†Œ๊ฐ’์„ ๋น„๊ตํ•˜๋Š” ๊ณผ์ •์ด ์ค‘๋ณต๋œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ์ฒ˜์Œ์— ์ฃผ์–ด์ง„ index๋ฅผ ๋‚˜๋ˆ„์–ด, ๊ทธ ๋‚˜๋ˆˆ ๊ตฌ๊ฐ„์— ๋Œ€ํ•ด ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•ด๋†“์œผ๋ฉด ์–ด๋–จ๊นŒ?

์–ด๋–ป๊ฒŒ ๋‚˜๋ˆŒ๊นŒ?

๋‚˜๋ˆ„๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค๊ณ  ๋‚œ ํ›„์—๋Š”, ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ์ž˜ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์„ ์ง€์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ–ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ํŠธ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ์šฉ์ดํ•˜๋‹ค. ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ ์ค‘, ํƒ์ƒ‰์— ์žˆ์–ด ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ log์ด๋‹ค. ๋‚˜๋ˆ„๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ๊ฐ ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๋‹ค.

Tree ๊ตฌ์กฐ

ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋Š” ๋ชจ์–‘์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋ณดํ†ต ๊ฐ€์ง€๋Š” ์„ ํ˜• ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐ๊ธˆ ๋ฐ”๊พธ์–ด ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๊ฒŒ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ 2์˜ ์ œ๊ณฑ์ˆ˜๋งŒํผ์˜ ๊ฐœ์ˆ˜๋ฅผ ์•„๋ž˜์ชฝ์œผ๋กœ ์˜ฎ๊ธฐ๋ฉด์„œ ์Œ“์œผ๋ฉด ํŠธ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ๋œ๋‹ค. ์ด ๋•Œ, ์ค‘์š”ํ•œ ๊ฒƒ์€ ๊ฐ€์žฅ ์œ„์ธต์œผ๋กœ ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ๋‚ด๋ ค์˜ค๋Š”๋ฐ ๊ทธ index๋“ค์˜ ๊ด€๊ณ„๋ฅผ ์•„๋Š” ๊ฒƒ์ด๋‹ค. ์ž˜ ๋ณด๋ฉด, 1์—์„œ 2, 3์€ , ๊ณผ ๊ฐ™๋‹ค. ์™ผ์ชฝ ํŠธ๋ฆฌ, ์˜ค๋ฅธ์ชฝ ํŠธ๋ฆฌ๋กœ ๊ฐ€๋Š” ๊ด€๊ณ„๋Š” ๊ณ„์† ์ผ๊ด€์„ฑ์„ ๊ฐ€์ง„๋‹ค.

Segment Tree

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋ฒˆ์—๋Š” ์ด ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ด ๋ฌธ์ œ์— ๋งž๋Š” ๋ชจ์–‘์œผ๋กœ ๋ฐ”๊พธ์–ด ๋ณด์ž. ์šฐ๋ฆฌ๋Š” ์ตœ์†Œ๊ฐ’์„ ๋ฏธ๋ฆฌ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋ฆฌ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋Š”๋ฐ, ๊ทธ ๊ตฌ์กฐ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด์„œ ์ƒ๊ฐํ•ด๋ณด์ž.

๊ธฐ๋ณธ์ ์ธ ํŠธ๋ฆฌ๊ตฌ์กฐ๋Š” ๊ฐ™์ง€๋งŒ ์ถ”๊ฐ€๋œ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๊ทธ๊ฒƒ์€ index์˜ ์‹œ์ž‘๊ณผ ๋์„ ๋‚˜ํƒ€๋‚ด๋Š” startend ๋ณ€์ˆ˜์ด๋‹ค. ์ด๋ ‡๊ฒŒ ๋‚˜๋ˆ„์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , 25๊นŒ์ง€์˜ ์ตœ์†Œ๊ฐ’์„ ์–ป๊ธฐ์œ„ํ•ด ์กฐ์‚ฌํ•ด์•ผ ํ•˜๋Š” Node์˜ ๊ฐœ์ˆ˜๋ฅผ ํŒŒ์•…ํ•ด๋ณด์ž.

์ด๋ ‡๊ฒŒ 3๊ฐœ์˜ ๊ฐ’๋งŒ ์กฐ์‚ฌํ•˜๋ฉด ์ตœ์†Œ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค! ์ด ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ์ด๋‹ค. depth๊ฐ€ ๋‚ด๋ ค๊ฐˆ ์ˆ˜๋ก ๋ฐ˜์”ฉ ์กฐ์‚ฌ๋ฅผ ๋œ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

tree์— ํ•„์š”ํ•œ node ์ˆ˜

์œ„ ์˜ˆ์‹œ์—์„œ ์ด 7๊ฐœ์˜ ์›์†Œ๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ node์˜ ๊ฐœ์ˆ˜๋Š” ์ด 13๊ฐœ ์ด๋‹ค. ์ด 13๊ฐœ๋ฅผ ๋‹ค ๋„ฃ๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํŠธ๋ฆฌ์˜ ๊นŠ์ด๋Š” ์ด 4์ด๋‹ค. ์ด ๊ฐ’์„ ์–ป๊ธฐ ์œ„ํ•œ ์ˆ˜์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๋ณดํ†ต์˜ tree๋Š” input์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์†Œ์˜ ๊ฐœ์ˆ˜์™€ ํŠธ๋ฆฌ์˜ node๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€๋งŒ, ์ด ๊ฒฝ์šฐ๋Š” depth๊ฐ€ 1๊ฐœ ์ถ”๊ฐ€๋˜๋ฏ€๋กœ 1์„ ๋”ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์„ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

h = ceil(log2(n))+1;
treeSize = (1 << h);

<<์€ shift ์—ฐ์‚ฐ์ž๋กœ, 2์ง„ ์—ฐ์‚ฐ์„ ํ•  ๋•Œ, ์ž๋ฆฌ์ˆ˜๋ฅผ ์˜ฌ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

init (์ดˆ๊ธฐํ™”)

์ฒ˜์Œ์— input์„ ๋ฐ›๊ณ ์„œ, ๊ฐ€์žฅ ๋จผ์ € ํ•ด์•ผํ•˜๋Š” ์ผ์€, input์„ tree์•ˆ์— ๋„ฃ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์šฐ๋ฆฌ๊ฐ€ ์„ค๊ณ„ํ•œ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋ฉด, ์ด ์นœ๊ตฌ๋Š” ์•„๋ž˜ node๊ฐ€ ๊ฒฐ์ •๋œ ๋’ค์— ์ƒ์œ„ ๋…ธ๋“œ๊ฐ€ ๊ฒฐ์ •๋  ์ˆ˜ ์žˆ๋‹ค. ์žฌ๊ท€๋กœ ์งœ๋ฉด ํ•ด๊ฒฐ๋  ๊ฒƒ์ด๋‹ค.

void init(vector<int>& input, vector<int>& tree, int node, int start, int end){
    if (start == end) {
        tree[node] = input[start];
        return;
    }
    init(input, tree, 2*node, start, (start+end)/2);
    init(input, tree, 2*node+1, (start+end)/2+1, end);
    tree[node] = min(tree[2*node], tree[2*node+1]);
    return;
}

init ํ•จ์ˆ˜์˜ argument๋กœ๋Š” input ๋ฒกํ„ฐ, tree ๋ฒกํ„ฐ, ๋‚ด๊ฐ€ ๊ธฐ๋กํ•  node์˜ index, ์ฒ˜์Œ node๊ฐ€ ์ปค๋ฒ„ํ•˜๊ฒŒ ๋  index์˜ ์‹œ์ž‘๊ณผ ๋์ด ํ•„์š”ํ•˜๋‹ค. ๊ทธ ๋’ค๋กœ๋Š” ์•„๊นŒ ํŠธ๋ฆฌ ๊ตฌ์กฐ์—์„œ ๋ณธ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋กœ ๊ฐ€๋Š” ํ•จ์ˆ˜ ๊ด€๊ณ„์— ๋”ฐ๋ผ initํ•จ์ˆ˜๋ฅผ ๊ณ„์† ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค. ์ข…๋ฃŒ์กฐ๊ฑด์€, ๊ทธ๋ฆผ์—์„œ ๋ณด์•˜๋“ฏ์ด start์™€ end๊ณผ ๊ฐ™์•„์ง€๋Š” ์ง€์ ์—์„œ input์— start ํ•ด๋‹นํ•˜๋Š” index์˜ ๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค.

find

์ €์žฅ๋œ ์ž๋ฃŒ๊ตฌ์กฐ์—์„œ ์ฐพ๋Š” ๊ณผ์ •์ด๋‹ค. ๋‚ด๊ฐ€ ์ฐพ์œผ๋ ค๊ณ  ํ•˜๋Š” ๋ฒ”์œ„์„ left, right ๋ผ ํ•˜๊ณ , ๋‚ด๊ฐ€ ์ฒ˜์Œ์— ํƒ์ƒ‰์„ ์‹œ์ž‘ํ•  ๋…ธ๋“œ์˜ ๋ฒˆํ˜ธ๋ฅผ node, ๊ทธ ๋…ธ๋“œ๊ฐ€ ์ปค๋ฒ„ํ•˜๋Š” index์˜ ๋ฒ”์œ„๋ฅผ start, end๋ผ ํ•˜์ž. tree์˜ ๊ฐ€์žฅ ์œ„๋ถ€ํ„ฐ ํƒ์ƒ‰์„ ์‹œ์ž‘ํ•  ๋•Œ, ๋ฒ”์œ„์— ๊ฑธ๋ฆฌ๋Š” ๋…€์„๋“ค๋งŒ ๋น„๊ต์˜ ๋Œ€์ƒ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๋Ÿฐ ๋ฒ”์œ„๋ฅผ ๋”ฐ์ ธ๋ณด๋ฉด ์ด 3๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  1. left, right ์‚ฌ์ด์— ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ปค๋ฒ„๋ฒ”์œ„๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.
    • ํ›„๋ณด๋กœ ์„ ์ •ํ•œ๋‹ค.
  2. left, right ์™€ ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ปค๋ฒ„๋ฒ”์œ„๊ฐ€ ์ „ํ˜€ ๊ฒน์น˜์ง€ ์•Š๋Š”๋‹ค.
    • ๋ฒ„๋ฆฐ๋‹ค.
  3. ์• ๋งคํ•˜๊ฒŒ ๊ฑธ์นœ๋‹ค.
    • ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€์„œ ์กฐ์‚ฌํ•œ๋‹ค.

์ด ๊ณผ์ •์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

int findMin(vector<int>& tree, int node, int start, int end, int left, int right){
    if (left > end || right < start) {
        return INF;
    } else if (left <= start && end <= right){
        return tree[node];
    }
    int a = findMin(tree, 2*node, start, (start+end)/2, left, right);
    int b = findMin(tree, 2*node+1, (start+end)/2+1, end, left, right);
    return min(a, b);
}

Code

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
 
const int INF = 1111111111;
 
void init(vector<int>& input, vector<int>& tree, int node, int start, int end){
    if (start == end) {
        tree[node] = input[start];
        return;
    }
    init(input, tree, 2*node, start, (start+end)/2);
    init(input, tree, 2*node+1, (start+end)/2+1, end);
    tree[node] = min(tree[2*node], tree[2*node+1]);
    return;
}
 
int findMin(vector<int>& tree, int node, int start, int end, int left, int right){
    if (left > end || right < start) {
        return INF;
    } else if (left <= start && end <= right){
        return tree[node];
    }
    int a = findMin(tree, 2*node, start, (start+end)/2, left, right);
    int b = findMin(tree, 2*node+1, (start+end)/2+1, end, left, right);
    return min(a, b);
}
 
 
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    int n, m;
    cin >> n >> m;
    int h = int(ceil(log2(n)))+1;
    int treeSize = (1 << h);
    vector<int> tree(treeSize, INF);
    vector<int> a(n);
 
    for (int i = 0; i < n; i++) {
       cin >> a[i];
    }
    init(a, tree, 1, 0, n-1);
 
    for (int i = 0; i < m; i++) {
        int left, right;
        cin >> left >> right;
        cout << findMin(tree, 1, 0, n-1, left-1, right-1) << '\n';
    }
 
}

Reference