lowerBound와 upperBound를 활용하여 풀 수있는 문제였다.
총의 사정거리 L에대해 사대의 위치 와 동물의 위치 x,y에 대해 다음과 같은 공식이 문제에 주어져있다.
| 사대 - x | + y <= L
이 공식을 사대를 기준으로 다시정리해보았다.
| 사대 - x | + y <= L
| 사대 - x | <= L - y
- L + y <= 사대 - x <= L - y
- L + x + y <= 사대 <= L +x - y
이렇게 된다면 x,y 위치의 동물은 사정거리가 L 일때 - L + x + y 부터 L + x - y 사이의 사냥꾼이 한명이라도 존재하게 된다면 잡히게 되는 상황이 오게된다. 다만 L의 범위가 최대 1000000000이게 되므로 사대에 사냥꾼이 존재하는지를 확인하는 과정에서 일반적으로 접근했을때 시간초과가 발생할 수 있다. 따라서 이 과정에서 lowerBound와 upperBound를 활용해보았다.
lowerBound는 arr에서 주어진 값과 같거나 큰 값이 나오는 첫번째 위치의 인덱스를 리턴해주고, upperBound는 arr에서 주어진 값보다 큰 값이 나오는 첫번째 위치의 인덱스를 리턴해주게 된다. 따라서 upperBound(L + x - y)의 값에서 lowerBound(- L + x + y)의 값을 빼주면 - L + x + y에서 L + x - y사이의 존재하는 사냥꾼의 수를 구할 수 있다.
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
|
package algosutdy1;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main_bj_8983_사냥꾼 {
static int N, M, L;
static int[] shotArea;
static int answer;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
L = Integer.parseInt(st.nextToken());
shotArea = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
shotArea[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(shotArea);
answer = 0;
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
if (y > L) {
continue;
}
check(x, y);
}
System.out.println(answer);
}
static void check(int x, int y) {
int minX = -L + y + x;
int maxX = L - y + x;
if (upperBound(maxX) - lowerBound(minX) > 0) {
answer += 1;
}
}
static int lowerBound(int value) {
int startIndex = 0;
int endIndex = N;
while (startIndex < endIndex) {
int midIndex = (startIndex + endIndex) / 2;
if (shotArea[midIndex] < value) {
startIndex = midIndex + 1;
} else {
endIndex = midIndex;
}
}
return endIndex;
}
static int upperBound(int value) {
int startIndex = 0;
int endIndex = N;
while (startIndex < endIndex) {
int midIndex = (startIndex + endIndex) / 2;
if (shotArea[midIndex] <= value) {
startIndex = midIndex + 1;
} else {
endIndex = midIndex;
}
}
return endIndex;
}
}
|
위의 방법에선 lowerBound와 upperBound를 이용해 - L + x + y에서 L + x - y사이의 존재하는 사냥꾼의 수를 구하였지만 간단하게 이분탐색으로 아래 코드와 같은 방법으로 - L + x + y에서 L + x - y사이의 존재하는 사냥꾼의 수를 구할 수도 있다.
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
|
package algosutdy1;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main_bj_8993_사냥꾼_2 {
static int M, N, L;
static int[] shotArea;
static int answer;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
M = Integer.parseInt(st.nextToken());
N = Integer.parseInt(st.nextToken());
L = Integer.parseInt(st.nextToken());
shotArea = new int[M];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < M; i++) {
shotArea[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(shotArea);
answer = 0;
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
if (y > L) {
continue;
}
int minX = -L + x + y;
int maxX = L + x - y;
binarySearch(minX, maxX);
}
System.out.println(answer);
}
static void binarySearch(int minX, int maxX) {
int leftIndex = 0;
int rightIndex = M - 1;
while (leftIndex <= rightIndex) {
int midIndex = (leftIndex + rightIndex) / 2;
if (minX <= shotArea[midIndex] && shotArea[midIndex] <= maxX) {
answer += 1;
break;
}
if (shotArea[midIndex] < minX) {
leftIndex = midIndex + 1;
} else if (maxX < shotArea[midIndex]) {
rightIndex = midIndex - 1;
}
}
}
}
|
'Algorithm' 카테고리의 다른 글
[BOJ] 3020. 개똥벌레 (0) | 2021.06.02 |
---|---|
[Programmers] 징검다리 (2) | 2021.06.02 |
[BOJ] 4485. 녹색 옷 입은 애가 젤다지? (0) | 2021.05.24 |
[BOJ] 14442. 벽 부수고 이동하기2 (0) | 2021.05.16 |
[BOJ] 2812. 크게 만들기 (0) | 2021.05.15 |