https://www.acmicpc.net/problem/1927
1) x != 0 인 경우
PriorityQueue
에 x 추가2) x == 0 인 경우
PriorityQueue
가 not emptyPriorityQueue
에서 remove 및 출력PriorityQueue
가 emptyPriorityQueue<Integer>
: 입력 정수 x 저장 및 정렬import java.io.*;
import java.util.PriorityQueue;
public class Main_PriorityQueue {
static int n; // 수행할 연산 개수
static int x; // 정수 x
static PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> {
int absDiff = Math.abs(o1) - Math.abs(o2);
if (absDiff != 0)
return absDiff;
else
return o1 - o2;
});
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringBuilder sb = new StringBuilder();
n = Integer.parseInt(br.readLine());
for (int i = 0; i < n; i++) {
x = Integer.parseInt(br.readLine());
if (x != 0)
pq.add(x);
else { // x == 0
if (!pq.isEmpty())
sb.append(pq.remove()).append("\n");
else
sb.append(0).append("\n");
}
}
System.out.println(sb.toString());
}
}
Abs Heap 구현
- 최소 절댓값 노드가 루트 노드 arr[1]에 위치
(쉬운 구현을 위해 arr[0]은 사용 X)- 부모, 자식 index 번호 관계
=> 왼쪽 자식의 index = 부모의 index 2
=> 오른쪽 자식의 index = (부모의 index 2) + 1
=> 부모의 index = 자식의 index / 2
- void add(int item)
1) 맨 뒤 arr[size+1]에 새로운 item 추가
2) 새로운 노드 arr[size+1]을 부모 노드들과 비교해가면서 힙 정렬
=> ReHeapification Upward
① |부모| > |자식| 이면 교체
② |부모| == |자식| 이면, 더 작은 값이 부모가 됨
- int remove()
1) 루트 노드 arr[1]을 삭제
2) 빈 루트 노드 arr[1]를 마지막 노드 arr[size]로 채움
2) 루트 노드 arr[1] ~ arr[size-1] 까지 내려가면서 부모, 자식 비교해가면서 힙 정렬
=> ReHeapification Downward
① 왼쪽, 오른쪽 자식 노드 중, 절댓값이 더 작은 노드와 부모를 교체
② |왼쪽 자식| == |오른쪽 자식| 이면, 더 작은 값이 부모가 됨
AbsHeap
: 구현한 절댓값 힙import java.io.*;
class AbsHeap {
private int[] arr;
private int size;
public AbsHeap(int length) {
arr = new int[length];
}
public void add(int item) {
arr[++size] = item;
// Upward
for (int i = size; i > 1; i /= 2) {
int absParent = Math.abs(arr[i / 2]);
int absChild = Math.abs(arr[i]);
if (absParent > absChild) // |부모| > |자식|
swap(i / 2, i);
else if (absParent == absChild) { // |부모| == |자식|
if (arr[i / 2] > arr[i]) // 부모 > 자식
swap(i / 2, i);
}
else
break;
}
}
public int remove() {
int root = arr[1]; // 기존 루트 노드 (최소 절댓값)
arr[1] = arr[size--]; // 빈 루트 노드를 맨 뒤의 노드로 채움
// Downward
for (int i = 1; i * 2 <= size; ) {
int absParent = Math.abs(arr[i]);
int absLeftChild = Math.abs(arr[i * 2]);
int absRightChild = Math.abs(arr[i * 2 + 1]);
// |부모| < |자식| 또는
// |부모| == |자식| && 부모 < 자식
boolean isLeftSorted = (absParent < absLeftChild) ||
(absParent == absLeftChild && arr[i] < arr[i * 2]);
boolean isRightSorted = (absParent < absRightChild) ||
(absParent == absRightChild && arr[i] < arr[i * 2 + 1]);
if (isLeftSorted && isRightSorted)
break;
else if (absLeftChild < absRightChild) { // 절댓값이 더 작은 자식과 부모 교체
swap(i, i * 2);
i = i * 2;
}
else if (absLeftChild > absRightChild) { // 절댓값이 더 작은 자식과 부모 교체
swap(i, i * 2 + 1);
i = i * 2 + 1;
}
else { // |왼쪽 자식| == |오른쪽 자식| => 값이 더 작은 자식과 부모 교체
if (arr[i * 2] < arr[i * 2 + 1]) {
swap(i, i * 2);
i = i * 2;
}
else {
swap(i, i * 2 + 1);
i = i * 2 + 1;
}
}
}
return root;
}
public int size() { return size; }
public boolean isEmpty() { return size == 0; }
private void swap(int idx1, int idx2) {
int temp = arr[idx1];
arr[idx1] = arr[idx2];
arr[idx2] = temp;
}
}
public class Main_DevHeap {
static int n; // 수행할 연산 개수
static int x; // 입력 정수 x
static AbsHeap absHeap;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringBuilder sb = new StringBuilder();
n = Integer.parseInt(br.readLine());
absHeap = new AbsHeap(n + 1);
for (int i = 0; i < n; i++) {
x = Integer.parseInt(br.readLine());
if (x != 0)
absHeap.add(x);
else { // x == 0
if (!absHeap.isEmpty())
sb.append(absHeap.remove()).append("\n");
else
sb.append(0).append("\n");
}
}
System.out.println(sb.toString());
}
}