사냥꾼(이진탐색)

exsoul·2022년 6월 15일
0

문제 설명


KOI 사냥터에는 N 마리의 동물들이 각각 특정한 위치에 살고 있다. 사냥터에 온 사냥꾼은 일직선상에 위치한 M 개의 사대(총을 쏘는 장소)에서만 사격이 가능하다. 편의상, 일직선을 x-축이라 가정하고, 사대의 위치 x1, x2, ... xM 은 x-좌표 값이라고 하자. 각 동물이 사는 위치는 (a1, b1), (a2, b2), ..., (aN, bN) 과 같이 x, y-좌표 값으로 표시하자. 동물의 위치를 나타내는 모든 좌표 값은 양의 정수이다.

사냥꾼이 가지고 있는 총의 사정거리가 L 이라고 하면, 사냥꾼은 한 사대에서 거리가 L 보다 작거나 같은 위치의 동물들을 잡을 수 있다고 한다. 단, 사대의 위치 xi와 동물의 위치 (aj,bj) 간의 거리는 |xi-aj| + bj 로 계산한다.

예를 들어, 아래의 그림과 같은 사냥터를 생각해보자. (사대는 작은 사각형으로, 동물의 위치는 작은 원으로 표시되어 있다.) 사정거리 L이 4라고하면, 점선으로 표시된 영역은 왼쪽에서 세 번째 사대에서 사냥이 가능한 영역이다.

사대의 위치와 동물들의 위치가 주어졌을 때, 잡을 수 있는 동물의 수를 출력하는 프로그램을 작성하시오.

입력 설명


입력의 첫 줄에는 사대의 수 M(1≤M≤100,000) 동물의 수 N(1≤N≤100,000), 사정거리 L(1≤L≤1,000,000,000)이 빈칸을 사이에 두고 주어진다. 두 번째 줄에는 사대의 위치를 나타내는 M개의 x-좌표 값이 빈칸을 사이에 두고 양의 정수로 주어진다. 이후 N 개의 각 줄에는 각 동물의 사는 위치를 나타내는 좌표 값이 x-좌표 값, y-좌표 값의 순서로 빈칸을 사이에 두고 양의 정수로 주어진다. 사대의 위치가 겹치는 경우는 없으며, 동물들의 위치가 겹치는 경우도 없다. 모든 좌표 값은 1,000,000,000 보다 작거나 같은 양의 정수이다.

출력 설명


출력은 단 한 줄이며, 잡을 수 있는 동물의 수를 음수가 아닌 정수로 출력한다.

입력 예시


4 8 4
6 1 4 9
7 2
3 3
4 5
5 1
2 2
1 4
8 4
9 4

출력 예시


6

#include <stdio.h>
#include <stdlib.h>
#define MAXMN ((int)1e5)
int M, N, L;
int X[MAXMN+10];
int A[MAXMN+10];
int B[MAXMN+10];
 
int ABS(int x){
    return (x < 0) ? -x : x;
}
int SolveNM(void){
    int cnt = 0;
    for(int i=0; i<N; i++){//동물
        for (int j=0; j<M; j++){//사대
            if (ABS(X[j] - A[i]) + B[i] <= L) {
                cnt++;
                break;
            }
        }
    }
    return cnt;
}
 
int comp(const void *a, const void *b){
    return *(int*)a - *(int*)b;
}
 
int Bslow(int s, int e, int d){//d값 보다 크거나 같은 값 중에 제일 작은 인덱스
    int sol = -1;
    while (s <= e){
        int m = (s+e)/2;
        if (X[m] >= d){
            sol=m; e=m-1;
        }
        else{
            s=m+1;
        }
    }
    return sol;
}
 
int Solve(void){//O(N logM)
    int cnt = 0;
    qsort(X, M, sizeof(X[0]), comp);//오름차순 정렬
    for(int i=0; i<N; i++){//동물
        if (B[i] > L) continue;//무조건 못 잡음
        int low = A[i] + B[i] - L;//i번 동물을 잡을 수 있는 사대 좌표 하한
        int up = L + A[i] - B[i];//i번 동물을 잡을 수 있는 사대 좌표 상한
        int idx = Bslow(0, M-1, low);
        if ((idx < 0) || (X[idx] > up)) continue;//잡을 수 있는 사대 없음
        cnt++;
    }
    return cnt;
}
 
void InputData(void){
    scanf("%d %d %d", &M, &N, &L);
    for (int i=0; i<M; i++){
        scanf("%d", &X[i]);
    }
    for (int i=0; i<N; i++){
        scanf("%d %d", &A[i], &B[i]);
    }
}
 
int main(void){
    int ans = -1;
 
    InputData();// 입력받는 부분
 
    //ans = SolveNM();//여기서부터 작성
    ans = Solve();//여기서부터 작성
 
    printf("%d\n", ans);// 출력하는 부분
    return 0;
}
profile
ocho

0개의 댓글