본문 바로가기
알고리즘/BAEKJOON

BOJ 2357 : 최솟값과 최댓값

by 피로물든딸기 2023. 1. 16.
반응형

알고리즘 문제 전체 링크

 

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

 

참고
- 구간 합 구하기 with 탑 다운 세그먼트 트리 (Top-Down Segment Tree)
- 구간 합 구하기 with 바텀 업 세그먼트 트리 (Bottom-Up Segment Tree)

- BOJ 10868 : 최솟값

 

 

BOJ 10868에서 답을 구한 방법으로 최솟값을 구할 수 있고, 응용하면 최댓값도 구할 수 있다.

따라서 세그먼트 트리를 2개 이용하면 된다.

 

하지만 구조체로 묶으면 조금 더 간편하다.

TREE 라는 구조체를 선언해서 min과 max를 동시에 관리한다.

typedef struct st
{
	int min;
	int max;
}TREE;

 

init에는 leftTree와 rightTree에서 각각 더 작은 값과 더 큰 값을 갱신하면 된다.

TREE init(int left, int right, int node)
{
	if (left == right)
	{
		tree[node].min = tree[node].max = arr[left];
		return tree[node];
	}

	int mid = (left + right) / 2;

	TREE leftTree = init(left, mid, node * 2);
	TREE rightTree = init(mid + 1, right, node * 2 + 1);

	tree[node].min = isMin(leftTree.min, rightTree.min);
	tree[node].max = isMax(leftTree.max, rightTree.max);

	return tree[node];
}

 

getTree도 마찬가지로 적용하면 된다.

전체 코드를 참고하자.

#include <stdio.h>

int N, M;
int arr[100100];

typedef struct st
{
	int min;
	int max;
}TREE;

TREE tree[400400];

int isMin(int a, int b)
{
	return (a < b) ? a : b;
}

int isMax(int a, int b)
{
	return (a > b) ? a : b;
}

TREE init(int left, int right, int node)
{
	if (left == right)
	{
		tree[node].min = tree[node].max = arr[left];
		return tree[node];
	}

	int mid = (left + right) / 2;

	TREE leftTree = init(left, mid, node * 2);
	TREE rightTree = init(mid + 1, right, node * 2 + 1);

	tree[node].min = isMin(leftTree.min, rightTree.min);
	tree[node].max = isMax(leftTree.max, rightTree.max);

	return tree[node];
}

TREE getTree(int left, int right, int a, int b, int node)
{
	if (b < left || right < a)
	{
		TREE ret = { 0 };
		
		ret.min = 0x7fff0000;

		return ret;
	}

	if (a <= left && right <= b) return tree[node];

	int mid = (left + right) / 2;

	TREE leftTree = getTree(left, mid, a, b, node * 2);
	TREE rightTree = getTree(mid + 1, right, a, b, node * 2 + 1);

	TREE ret;

	ret.min = isMin(leftTree.min, rightTree.min);
	ret.max = isMax(leftTree.max, rightTree.max);

	return ret;
}

int main()
{
	scanf("%d %d", &N, &M);

	for (int i = 1; i <= N; i++) scanf("%d", &arr[i]);

	init(1, N, 1);

	for (int i = 0; i < M; i++)
	{
		int a, b;

		scanf("%d %d", &a, &b);

		TREE tmp = getTree(1, N, a, b, 1);

		printf("%d %d\n", tmp.min, tmp.max);
	}

	return 0;
}

Bottom-Up 방식은 다음과 같다.

주어지는 정수가 1 이상이기 때문에 max 값을 음수로 변경하지는 않는다.

#include <stdio.h>

int N, M;

typedef struct st
{
	int min;
	int max;
}TREE;

TREE tree[400400];
int start;


int isMin(int a, int b)
{
	return (a < b) ? a : b;
}

int isMax(int a, int b)
{
	return (a > b) ? a : b;
}

void update(int index, int value)
{
	index += start;

	while (index > 1)
	{
		tree[index].min = isMin(tree[index].min, value);
		tree[index].max = isMax(tree[index].max, value);

		index /= 2;
	}
}

TREE getTree(int left, int right)
{
	TREE ans;

	ans.min = 0x7fff0000;
	ans.max = 0;

	left += start;
	right += start;

	while (left < right)
	{
		if (left % 2 == 0) left /= 2;
		else
		{
			ans.min = isMin(ans.min, tree[left].min);
			ans.max = isMax(ans.max, tree[left].max);

			left += 1;
			left /= 2;
		}

		if (right % 2 == 1) right /= 2;
		else
		{
			ans.min = isMin(ans.min, tree[right].min);
			ans.max = isMax(ans.max, tree[right].max);

			right -= 1;
			right /= 2;
		}
	}

	if (left == right)
	{
		ans.min = isMin(ans.min, tree[left].min);
		ans.max = isMax(ans.max, tree[left].max);
	}

	return ans;
}

int main()
{
	int n;

	scanf("%d %d", &N, &M);

	for (n = 1; (1 << n) <= N; n++);
	start = 1 << n;
	start--;

	int maxTreeIndex = (1 << (n + 1));
	for (int i = 0; i <= maxTreeIndex; i++) tree[i].min = 0x7fff0000;

	for (int i = 1; i <= N; i++)
	{
		int x;

		scanf("%d", &x);

		update(i, x);
	}

	for (int i = 0; i < M; i++)
	{
		int a, b;

		scanf("%d %d", &a, &b);

		TREE tmp = getTree(a, b);

		printf("%d %d\n", tmp.min, tmp.max);
	}

	return 0;
}
반응형

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

BOJ 1655 : 가운데를 말해요 with 세그먼트 트리  (0) 2023.01.19
BOJ 5397 : 키로거  (0) 2023.01.18
BOJ 10868 : 최솟값  (0) 2023.01.16
BOJ 1708 : 볼록 껍질  (0) 2022.12.28
BOJ 1935 : 후위 표기식2  (1) 2022.12.26

댓글