문제 링크
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명
접근 방법
이 문제에 핵심
1. N 그루의 나무는 각 특정 위치에 존재하고 있습니다.
2. 특정 위치에서 나무 사진을 찍을 때 점수는 나무까지 거리의 합입니다.
3. Q개의 위치가 주어질 때 각 사진의 점수를 결과로 출력합니다.
알고리즘 진행 순서.
1. 입력된 정보를 저장합니다.
2. 누적합을 이용하여 1 ~ 최대 위치 기준 거리를 탐색합니다.
3. 탐색으로 얻은 각 위치에 대한 사진의 점수를 결과로 출력합니다.
사진 점수 구하기(누적합)
주어진 사진 찍는 위치에서 매 번 나무의 거리를 구할 수 있지만, 나무의 개수와 주어지는 위치의 개수가 크기 때문에 시간초과가 발생합니다.
1. 위치에 따른 나무의 거리 변화량
만약 사진찍는 위치를 빨간색 ▶︎ 하늘색으로 이동할 때에 나무까지의 거리 변화량을 살펴보면 아래와 같습니다.
즉, 이동하는 방향과 거리에 따라 특정 위치에서 나무의 거리가 변화됩니다.
위치가 1일 때 각 나무의 거리를 구한 뒤 +1씩 거리를 이동하면서 각 나무의 변화량에 맞게 변경시켜주시면 됩니다.
+1씩 지나가는 것으로 왼쪽의 나무의 수만큼 거리가 증가하고 오른쪽에 있는 나무의 수만큼 거리가 감소하게 됩니다.
예를 들어,
현재 위치 : x
왼쪽 나무의 수 : 3 그루
오른쪽 나무의 수 : 5그루
(x+1)칸으로 이동하였을 때 나무의 거리 : x칸 나무의 거리 + 3(왼쪽) - 5(오른쪽)
위와 같이 문제 1 ~ 주어진 특정 최대 위치까지 나무의 거리를 계산을 진행합니다.
계산한 위치를 기준으로 특정 위치들의 나무 거리를 결과로 출력하게 됩니다.
예제입력 1.
1. 입력된 정보를 저장합니다.
N | Q |
5 | 2 |
사진 찍는 위치 | 4 | 12 |
2. 누적합을 이용하여 1 ~ 최대 위치 기준 거리를 탐색합니다.
3. 탐색으로 얻은 각 위치에 대한 나무의 거리를 결과로 출력합니다.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
25 | 22 | 19 | 18 | 17 | 16 | 15 | 16 | 17 | 20 | 25 | 30 |
- BufferedReader를 사용하여 입력되는 정보를 저장합니다.
- StringTokenizer을 통해서 나무 및 위치 정보 띄어쓰기 기준 나누었습니다.
- 위치 1을 기준으로 나무의 거리를 구한 뒤 왼쪽, 오른쪽 나무 개수를 세팅합니다.
- 1 ~ 최대 특정 위치까지 +1칸씩 이동하며 사진의 점수를 구합니다.
- 탐색을 통해 Q개 위치의 사진 점수를 BufferedWriter 저장합니다.
- BufferedWriter에 저장된 결과를 출력합니다.
결과코드
import java.io.*;
import java.util.*;
class Main {
public static void main(String[] args) throws Exception {
//입력값 처리하는 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//결과값 출력하는 BufferedWriter
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine()," ");
int[] pos = new int[n];
//위치가 1일 때 각 나무까지 거리의 합
long basicDistance = 0L;
//나무 정보 저장 및 정렬
for(int i=0;i<n;i++){
pos[i] = Integer.parseInt(st.nextToken());
//위치가 1일 때 각 나무까지 거리 구하기
basicDistance += pos[i] -1;
}
Arrays.sort(pos);
int[] targets = new int[m];
int maxPos = 0;
//목표 위치 저장 및 최대 위치 구하기
for(int i=0;i<m;i++){
targets[i] = Integer.parseInt(br.readLine());
maxPos = Math.max(maxPos, targets[i]);
}
//1 ~ 최대 위치 기준 나무 거리의 합 저장할 배열 설정
long[] distance = new long[maxPos+1];
distance[1] = basicDistance;
//위치 1 기준 왼쪽, 오른쪽 나무 개수 설정
int left = 0;
int right = n;
int idx = 0;
while(idx < n && pos[idx] == 1 ){
left++;
right--;
idx++;
}
//각 위치에서 왼쪽, 오른쪽 나무 개수를 이용해 거리 구하기
for(int i=2;i<=maxPos;i++){
distance[i]= distance[i-1] + left - right;
while(idx < n && pos[idx] == i){
left++;
right--;
idx++;
}
}
//목표 위치에 대한 결과값 BufferedWriter 저장
for(int target : targets){
bw.write(String.valueOf(distance[target]));
bw.newLine();
}
bw.flush(); //결과 출력
bw.close();
br.close();
}
}
'백준' 카테고리의 다른 글
[백준, Java] 2698번, 인접한 비트의 개수(DP) (0) | 2024.12.10 |
---|---|
[백준, Java] 2374번, 같은 수로 만들기(스택, 그리드) (0) | 2024.11.19 |
[백준, Java] 20955번, 민서의 응급 수술(Union-Find) (3) | 2024.11.13 |
[백준, Java] 7983번, 내일 할거야(그리디) (1) | 2024.11.09 |
[백준, Java] 14369번, 전화번호 수수께끼 (Small)(백트래킹) (0) | 2024.11.08 |
댓글