Compy's Blog
698 words
3 minutes
[BOJ] 사격
2024-10-04

사격

TimeLimitMemoryLimitConditionTAG
1s1024MB(1<=N, M, Sᵢ <= 10⁵,1<=A<=10¹⁰)binary search

성현이네 부대의 24-1분기 사격 훈련이 시작되었다! 성현이네 부대의 사격 훈련장에는 NN개의 표적이 있으며, 그중 ii번째 표적의 점수는 sis_i이다. 점수가 sis_i인 표적을 맞히기 위해선 사격 실력이 최소 sis_i 이상이어야 한다. 만약 해당 표적을 성공적으로 맞혔다면, 표적의 점수만큼 사격 점수를 획득하며 사격 실력도 동일한 만큼 증가한다. 이번 사격 훈련에서는 최대 MM번 사격할 수 있으며, 성현이가 진급에 성공하기 위해서는 획득한 사격 점수의 총합이 AA점 이상이어야 한다. 사격 훈련을 시작하기 전 초기 사격 점수는 00점이다. 성현이는 항상 자신이 맞힐 수 있는 표적 중 얻을 수 있는 사격 점수가 가장 높은 표적을 맞히며, 동일한 표적을 여러 번 맞히는 것도 가능하다. 진급이 절실했던 성현이는 사격 훈련이 시작하기 전 초기 사격 실력이 어느 정도여야 진급에 성공할 수 있을지 궁금해하고 있다. 성현이를 위해, 진급에 성공하기 위한 초기 사격 실력의 최솟값을 구해주자. 항상 진급에 성공할 수 있는 경우만 입력으로 주어진다.

우리는 문제를 보는 순간 아! 라고 외치지 않을까 한다.

느므느므 큰 범위를 보고, 값을 찾는 문제여서 바로 이분탐색으로 접근하였다.

(나중에 더욱 자세히 쓸 예정…)

정답 코드
#define MAX 2'100'000'000
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <math.h>
#include <random>
using namespace std;

using ull = unsigned long long;
using ll = long long;
int score[100001];
ull n, m, a;
bool visited[100001];
bool debug_ = false;
ull current_ = 0;
ull binary_search_(ull current, int depth){
    if(depth >= m|| current >= a) return current;
    int left = 0, right = n-1;
    current += current_;
    int val = -1;

    while(left < right ){
        int pivot = (left+ right) / 2;
        if(score[pivot] < current){
            if(pivot+1 < n && score[pivot+1] > current){
                val = score[pivot];
                break;
            }
            left = pivot+1;
            
            if(left < 0 || score[left] > current) continue;
            val = max(val, score[left]);
        }
        else if(score[pivot] > current){
            right = pivot - 1;
            if(right < 0|| score[right] > current) continue;
            val = max(val, score[right]);
        }
        else {val = score[pivot]; break;}

    }


    if(val == -1) val = score[left];
    if(val > current) return 0;
    current-=current_;
    ull result = binary_search_(current + val, depth+1);
    return result;
}

int main(){
    
    cin >> n >> m >> a;
    int limit = 0;
    for(int i = 0; i < n; i++){ cin >> score[i]; limit = max(limit, score[i]);}
    sort(score, score+n);
    if(n == 1){
        cout << score[0];
        return 0;
    }
    
    int left = 1, right = limit;
    ull result = MAX;
    while(left <= right){
        current_ = (left + right) / 2;
        ull tmp = binary_search_(0, 0);
        if(tmp >= a){
            result = min(current_, result);
            right = current_-1;
        }else{
            left = current_+1;
        }
    }
    cout << result;
    return 0;
}
[BOJ] 사격
https://compy07.github.io/Blog/posts/boj/31264/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2024-10-04