백준[baekjoon]/C언어

백준(baekjoon) [C] - 1655번: 가운데를 말해요

_KTH_ 2023. 2. 22. 23:52
728x90

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

 

1655번: 가운데를 말해요

첫째 줄에는 백준이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 백준이가 외치는 정수가 차례대로 주어진다. 정수는 -1

www.acmicpc.net


#include <stdio.h>  // 가운데를 말해요
#include <stdlib.h>

typedef struct
{
	int data;
}node;

typedef struct
{
	node arr[100001];
	int size;
}HEAP;

void max_push(HEAP* h, int num)
{
	int i;
	i = ++(h->size);
	while ((i != 1) && (num > h->arr[i / 2].data))
	{
		h->arr[i].data = h->arr[i / 2].data;
		i /= 2;
	}
	h->arr[i].data = num;
}

void min_push(HEAP* h, int num)
{
	int i;
	i = ++(h->size);
	while ((i != 1) && (num < h->arr[i / 2].data))
	{
		h->arr[i].data = h->arr[i / 2].data;
		i /= 2;
	}
	h->arr[i].data = num;
}

int max_pop(HEAP* h)
{
	int root = h->arr[1].data;
	int temp = h->arr[(h->size)--].data;

	int parent = 1;
	int child = 2;
	while (child <= h->size)
	{
		if ((child < h->size) && (h->arr[child].data < h->arr[child + 1].data))
		{
			child++;
		}

		if (temp >= h->arr[child].data)
		{
			break;
		}

		h->arr[parent].data = h->arr[child].data;
		parent = child;
		child *= 2;
	}
	h->arr[parent].data = temp;

	return root;
}

int min_pop(HEAP* h)
{
	int root = h->arr[1].data;
	int temp = h->arr[(h->size)--].data;

	int parent = 1;
	int child = 2;
	while (child <= h->size)
	{
		if ((child < h->size) && (h->arr[child].data > h->arr[child + 1].data))
		{
			child++;
		}

		if (temp <= h->arr[child].data)
		{
			break;
		}

		h->arr[parent].data = h->arr[child].data;
		parent = child;
		child *= 2;
	}
	h->arr[parent].data = temp;

	return root;
}


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

	HEAP min_h, max_h;
	min_h.size = max_h.size = 0;

	for (int i = 0; i < n; i++)
	{
		int num;
		scanf("%d", &num);
		
		if (max_h.size <= min_h.size)
		{
			max_push(&max_h, num);
		}
		else
		{
			min_push(&min_h, num);
		}

		while ((min_h.size > 0) && (max_h.arr[1].data > min_h.arr[1].data))
		{
			// max_heap, min_heap의 top 교환
			max_push(&max_h, min_pop(&min_h));
			min_push(&min_h, max_pop(&max_h));
		}

		printf("%d\n", max_h.arr[1].data);
	}

	return 0;
}

MEMO

-- 최대힙(max_h), 최소힙(min_h) 을 이용하여 해결

-- 최대힙과 최소힙에 번갈아가며 push

-- 만약 최대힙의 top이 최소힙의 top보다 크다면 두 값을 서로 교환(짝수개일 경우 더 작은 값을 선택하기 위해서)

-- 최대힙의 top이 항상 중간값

 

!! 구글링 전에 좀 더 고민해보기 !!

728x90
728x90