14427번: 수열과 쿼리 15
길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i v : Ai를 v로 바꾼다. (1 ≤ i ≤ N, 1 ≤ v ≤ 109) 2 : 수열에서 크기가 가장 작은 값의 인덱스를
www.acmicpc.net
문제 풀이
이 문제는 자료구조를 활용해서 문제를 푸는 것이 핵심이다. priority queue를 사용해서 O(logN)안에 수열에서 가장 큰 수를 뽑아낼 수 있다. 하지만 pq 내의 값을 변경해야 하는 경우가 생긴다. 이 때 pq내의 값을 직접 바꾸는 것이 아니라 값에 대한 version을 도입해서 최신 version의 값이 아니라면 pq에서 나온 값을 무시하는 식으로 코드를 짰다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int N = Integer.parseInt(in.readLine());
String[] str = in.readLine().split(" ");
//해당 인덱스의 버전을 기록하는 배열
int[] change_count = new int[N + 1];
PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if(o1[0] == o2[0]) return o1[1] - o2[1];
else return o1[0] - o2[0];
}
});
for(int i = 0; i < N; i++) {
int num =Integer.parseInt(str[i]);
pq.offer(new int[] {num, i + 1, 0});
}
int M = Integer.parseInt(in.readLine());
for(int i = 0; i < M; i++) {
String cmd = in.readLine();
if(cmd.equals("2")) { // 2명령일 때
int now[];
while(true) {
now = pq.peek();
//최신 버전이면
if(change_count[now[1]] == now[2]) {
sb.append(now[1] + "\n");
break;
}else { //최신 버전이 아니라면
pq.poll();
}
}
}
else { // 1명령일 때
String[] cmd1 = cmd.split(" ");
int num = Integer.parseInt(cmd1[2]);
int index = Integer.parseInt(cmd1[1]);
change_count[index]++;
pq.offer(new int[] {num, index, change_count[index]});
}
}
System.out.print(sb);
}
}