공부공간

BOJ - 2357 ) 최솟값과 최댓값 본문

알고리즘/SegmentTree

BOJ - 2357 ) 최솟값과 최댓값

개발자가될수있을까? 2020. 5. 16. 23:43

 


https://www.acmicpc.net/problem/2357

 

2357번: 최솟값과 최댓값

N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100

www.acmicpc.net


구간쿼리대 점갱신에 대표적인 예로, 구간에서 최댓값 최솟값 누적합.. 등등을 물어보는 쿼리에 대해 LogN에 

 

처리하기위해 전처리를 해준다. 사실 딱히 설명할게없다..

 

세그먼트트리 응용과 구간쿼리 구간갱신을 위한 Lazy Propagation을 공부해야겠다.



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class 최솟값과최댓값 {
	public static int maxseg[],minseg[];
	public static int number[];
	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 segsize = (int) Math.pow(2, Math.ceil(Math.log10(n)/Math.log10(2))+1 );
		maxseg = new int[segsize];
		minseg = new int[segsize];
		number = new int[n];
		for(int i = 0 ; i < n ; i++) {
			st= new StringTokenizer(br.readLine());
			number[i] =  Integer.parseInt(st.nextToken());
		}
		MinSegInit(1,0,n-1);
		MaxSegInit(1,0,n-1);
		for(int i = 0 ; i < m ; i++) {
			st = new StringTokenizer(br.readLine());
			int left = Integer.parseInt(st.nextToken())-1;
			int right = Integer.parseInt(st.nextToken())-1;
			int max = MaxQuery(1 , 0 , n-1 , left , right);
			int min = MinQuery(1 , 0 , n-1 , left , right);
			sb.append(min +"\n");
		}
		System.out.println(sb);
	}
	private static int MinQuery(int node, int start, int end, int left, int right) {
		if(end < left || start >  right) return 2147000000;
		if(left <= start && end <= right) return minseg[node];
		int mid = (start+end)>>1;
		return Math.min(MinQuery(2*node, start, mid, left, right), MinQuery(2*node+1, mid+1, end, left, right));
	}
	private static int MaxQuery(int node, int start, int end, int left, int right) {
		if(end < left || start >  right) return -1;
		if(left <= start && end <= right) return maxseg[node];
		int mid = (start+end)>>1;
		return Math.max(MaxQuery(2*node, start, mid, left, right), MaxQuery(2*node+1, mid+1, end, left, right));
	}
	private static int MaxSegInit(int node, int start, int end) {
		if(start== end) {return maxseg[node] = number[start];}
		int mid = (start+end)>>1;
		return maxseg[node] = Math.max(MaxSegInit(2*node, start, mid), MaxSegInit(2*node+1, mid+1, end));
	}
	private static int MinSegInit(int node, int start, int end) {
		if(start== end) {return minseg[node] = number[start];}
		int mid = (start+end)>>1;
		return minseg[node] = Math.min(MinSegInit(2*node, start, mid), MinSegInit(2*node+1, mid+1, end));
	}

}

크게 설명할게 없다..

 

'알고리즘 > SegmentTree' 카테고리의 다른 글

BOJ - 6549 ) 히스토그램에서 가장 큰 직사각형  (0) 2020.10.28
BOJ -2268 ) 수들의 합  (0) 2020.05.17
BOJ - 10868 ) 최솟값  (0) 2020.05.16
BOJ - 1275 ) 커피숍2  (0) 2020.05.16
BOJ - 2042 ) 구간 합 구하기  (0) 2020.03.17
Comments