-
[JAVA] 백준 2357 최솟값과 최댓값알고리즘 공부/문제 풀이 2021. 9. 29. 15:05
https://www.acmicpc.net/problem/2357
2357번: 최솟값과 최댓값
N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100
www.acmicpc.net
문제 분석
N개의 정수 범위에서 a ~ b까지의 최댓값과 최솟값을 구해라. a, b쌍이 최대 10만 개 주어질 수 있음!
=> 각 a, b의 쌍에 대해 최솟값과 최댓값을 구하면 시간초과 발생
해결 전략
구간 합을 로그의 시간복잡도롤 구할 수 있는 세그먼트 트리 (이진 트리의 형태로 왼쪽, 오른쪽 자식을 재귀적으로 탐색)
최댓값과 최솟값을 구하기 위한 세그먼트 트리를 만들자
- mode에 따라 최솟값, 최댓값 메서드 구현
- 리프 노드를 제외한 노드에는 최댓값과 최솟값의 정보를 가짐
- 기존의 sum 연산 대신 find 연산을 수행!
** root 노드는 1번 노드부터 init, find 메서드 시작, arr: 1번 부터 값 가지게 하기
코드
import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); StringBuilder sb = new StringBuilder(); int N = Integer.parseInt(st.nextToken()); int M = Integer.parseInt(st.nextToken()); int[] arr = new int[N+1]; for(int i=1;i<=N;i++) arr[i] = Integer.parseInt(br.readLine()); int[] maxTree = new int[4*N]; int[] minTree = new int[4*N]; init(arr, maxTree, 1, 1, N, 1); init(arr, minTree, 1, 1, N, 0); for(int i=0;i<M;i++){ st = new StringTokenizer(br.readLine()); int a = Integer.parseInt(st.nextToken()); int b = Integer.parseInt(st.nextToken()); int min = find(minTree, 1, 1, N, a, b, 0); int max = find(maxTree, 1, 1, N, a, b, 1); sb.append(min+" "+max).append('\n'); } System.out.println(sb); } public static int init(int[] arr, int[] tree, int node, int start, int end, int mode){ if(start==end) return tree[node] = arr[start]; int mid = (start+end)/2; int left = init(arr, tree, node*2, start, mid, mode); int right = init(arr, tree, node*2+1, mid+1, end, mode); if(mode==1) return tree[node] = Math.max(left, right); else return tree[node] = Math.min(left, right); } public static int find(int[] tree, int node, int start, int end, int left, int right, int mode){ if(end < left || start > right){ if(mode==0) return Integer.MAX_VALUE; else return 0; } if(left<=start && end<=right) return tree[node]; int mid = (start+end)/2; int lc = find(tree, node*2, start, mid, left, right, mode); int rc = find(tree, node*2+1, mid+1, end, left, right, mode); if(mode==0) return Math.min(lc, rc); else return Math.max(lc, rc); } }
'알고리즘 공부 > 문제 풀이' 카테고리의 다른 글
[JAVA] SWEA 탈주범 검거 (0) 2021.09.30 [JAVA] SWEA 보급로 (0) 2021.09.30 [JAVA] 백준 20056 마법사 상어와 파이어 볼 (0) 2021.09.29 [JAVA] 백준 1194 달이 차오른다, 가자 (0) 2021.09.29 [JAVA] SWEA Professional 구간 합 (0) 2021.09.28