πŸ•οΈ PS (BOJ)/Binary Search

[BOJ] λ°±μ€€ 10816번: 숫자 μΉ΄λ“œ 2 (Map 없이 μ΄λΆ„νƒμƒ‰λ§ŒμœΌλ‘œ ν’€κΈ°)

선달 2022. 10. 13. 17:15
λ°˜μ‘ν˜•

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

 

10816번: 숫자 μΉ΄λ“œ 2

첫째 쀄에 상근이가 κ°€μ§€κ³  μžˆλŠ” 숫자 μΉ΄λ“œμ˜ 개수 N(1 ≤ N ≤ 500,000)이 μ£Όμ–΄μ§„λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 숫자 μΉ΄λ“œμ— μ ν˜€μžˆλŠ” μ •μˆ˜κ°€ μ£Όμ–΄μ§„λ‹€. 숫자 μΉ΄λ“œμ— μ ν˜€μžˆλŠ” μˆ˜λŠ” -10,000,000보닀 ν¬κ±°λ‚˜ κ°™κ³ , 10,

www.acmicpc.net

 

문제

숫자 μΉ΄λ“œλŠ” μ •μˆ˜ ν•˜λ‚˜κ°€ μ ν˜€μ Έ μžˆλŠ” μΉ΄λ“œμ΄λ‹€. μƒκ·Όμ΄λŠ” 숫자 μΉ΄λ“œ N개λ₯Ό κ°€μ§€κ³  μžˆλ‹€. μ •μˆ˜ Mκ°œκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, 이 μˆ˜κ°€ μ ν˜€μžˆλŠ” 숫자 μΉ΄λ“œλ₯Ό 상근이가 λͺ‡ 개 κ°€μ§€κ³  μžˆλŠ”μ§€ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 상근이가 κ°€μ§€κ³  μžˆλŠ” 숫자 μΉ΄λ“œμ˜ 개수 N(1 ≤ N ≤ 500,000)이 μ£Όμ–΄μ§„λ‹€. λ‘˜μ§Έ μ€„μ—λŠ” 숫자 μΉ΄λ“œμ— μ ν˜€μžˆλŠ” μ •μˆ˜κ°€ μ£Όμ–΄μ§„λ‹€. 숫자 μΉ΄λ“œμ— μ ν˜€μžˆλŠ” μˆ˜λŠ” -10,000,000보닀 ν¬κ±°λ‚˜ κ°™κ³ , 10,000,000보닀 μž‘κ±°λ‚˜ κ°™λ‹€.

μ…‹μ§Έ μ€„μ—λŠ” M(1 ≤ M ≤ 500,000)이 μ£Όμ–΄μ§„λ‹€. λ„·μ§Έ μ€„μ—λŠ” 상근이가 λͺ‡ 개 κ°€μ§€κ³  μžˆλŠ” 숫자 μΉ΄λ“œμΈμ§€ ꡬ해야 ν•  M개의 μ •μˆ˜κ°€ μ£Όμ–΄μ§€λ©°, 이 μˆ˜λŠ” 곡백으둜 κ΅¬λΆ„λ˜μ–΄μ Έ μžˆλ‹€. 이 μˆ˜λ„ -10,000,000보닀 ν¬κ±°λ‚˜ κ°™κ³ , 10,000,000보닀 μž‘κ±°λ‚˜ κ°™λ‹€.

좜λ ₯

첫째 쀄에 μž…λ ₯으둜 μ£Όμ–΄μ§„ M개의 μˆ˜μ— λŒ€ν•΄μ„œ, 각 μˆ˜κ°€ 적힌 숫자 μΉ΄λ“œλ₯Ό 상근이가 λͺ‡ 개 κ°€μ§€κ³  μžˆλŠ”μ§€λ₯Ό 곡백으둜 ꡬ뢄해 좜λ ₯ν•œλ‹€.

 

풀이 1 - upperBound, lowerBound μ‚¬μš©

// Authored by : seondal
// Co-authored by : -

// #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

    int n, m;
    cin >> n;
    vector<int> arr(n,0);
    for(int i=0; i<n; i++)
        cin >> arr[i];
    
    sort(arr.begin(), arr.end());
    
    cin >> m;
    int input;
    while(m--) {
        cin >> input;
        int ans = upper_bound(arr.begin(), arr.end(), input) - lower_bound(arr.begin(), arr.end(), input);
        cout << ans << "\n";
    }
}

/*
 */

 

 

풀이2 - upperBound, lowerBound 직접 κ΅¬ν˜„

// Authored by : seondal
// Co-authored by : -

// #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int lowerBound(int left, int right, int target, vector<int> &arr) {
    while(left <= right) {
        int mid = (left+right) /2;
        
        if(arr[mid] >= target)
            right = mid-1;
        else
            left = mid+1;
    }
    
//    1. break 직전 left와 rightλŠ” 같은곳을 가리킴
//    2. arr[mid] λŠ” target 보닀 μž‘κΈ° λ•Œλ¬Έμ— left 포인터 이동
//    3. μ΄λ™ν•œ left 포인터값 = target의 인덱슀 => return
    
    return left;
}

int upperBound(int left, int right, int target, vector<int>&arr) {
    while(left <= right) {
        int mid = (left+right) / 2;
        
        if(arr[mid] <= target)
            left = mid+1;
        else
            right = mid-1;
    }
    
//    1. arr[mid] <= target이면 left 이동
//    2. arr[mid] == target이면 left = mid+1 ... left>target 인 μˆœκ°„ 멈좀
//    3. μ΄λ•Œ left κ°’ = upperBound!
    
    return left;
}
int main() {
    ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);

    int n, m;
    cin >> n;
    vector<int> arr(n,0);
    for(int i=0; i<n; i++)
        cin >> arr[i];
    
    sort(arr.begin(), arr.end());
    
    cin >> m;
    int input;
    while(m--) {
        cin >> input;
        int ans = upperBound(0, n-1, input, arr) - lowerBound(0, n-1, input, arr);
        cout << ans << "\n";
    }
}

/*
 */

 

λ°˜μ‘ν˜•