Post

BOJ_3015_오아시스 재결합

BOJ_3015_오아시스 재결합

[Platinum V] 오아시스 재결합 - 3015

문제 링크

성능 요약

메모리: 60024 KB, 시간: 432 ms

분류

자료 구조, 스택

제출 일자

2024년 8월 23일 10:42:10

문제 설명

오아시스의 재결합 공연에 N명이 한 줄로 서서 기다리고 있다.

이 역사적인 순간을 맞이하기 위해 줄에서서 기다리고 있던 백준이는 갑자기 자기가 볼 수 있는 사람의 수가 궁금해 졌다.

두 사람 A와 B가 서로 볼 수 있으려면, 두 사람 사이에 A 또는 B보다 키가 큰 사람이 없어야 한다.

줄에 서있는 사람의 키가 주어졌을 때, 서로 볼 수 있는 쌍의 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 줄에서 기다리고 있는 사람의 수 N이 주어진다. (1 ≤ N ≤ 500,000)

둘째 줄부터 N개의 줄에는 각 사람의 키가 나노미터 단위로 주어진다. 모든 사람의 키는 231 나노미터 보다 작다.

사람들이 서 있는 순서대로 입력이 주어진다.

출력

서로 볼 수 있는 쌍의 수를 출력한다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.io.*;
import java.util.*;

public class Main {

	/**
	 * height : 키
	 * num : 같은키 가진 연속된 사람 수
	 */
	static class Person {
		int height;
		int pairNum;

		public Person(int height, int pairNum) {
			this.height = height;
			this.pairNum = pairNum;
		}
		
	    @Override
	    public String toString() {
	        return "(" + height + "," + pairNum + ")";
	    }
	}

	static BufferedReader br;
	static int N, arr[];
	static long ans;
	static Stack<Person> stack;

	public static void main(String[] args) throws Exception {
//		br = new BufferedReader(new InputStreamReader(System.in));
		br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		N = Integer.parseInt(br.readLine());
		arr = new int[N];
		stack = new Stack<>();

		int i;
		for (i = 0; i < N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}

		/**
		 * 지금 사람보다 키가 작은 사람들은 모두 볼 수 있으므로 볼 수 있는 쌍의 수 추가하고 스택에서 제거.
		 * 자신보다 큰 사람은 1명만 볼 수 있음
		 * 최종적으로 스택에는 키가 중간중간 작은애들 빠지고 내림차순으로 남을것이다.
		 * 시간복잡도 O(N)
		 */
		
		long cnt = 1;
		int j;
		for (j = 0; j < N; j++) {
			int tmp = arr[j];
			int tmpNum = 1;

//	        System.out.println("\n처리 중인 사람: 키 " + tmp);
//	        System.out.println("처리 전 스택: " + stack);
	        
			// 현재 사람보다 키가 작은 사람들을 스택에서 제거하며 쌍의 수 추가
			while (!stack.isEmpty() && tmp > stack.peek().height) {
				ans += stack.peek().pairNum;
				stack.pop();
//	            System.out.println("팝: " + stack.pop() + ", ans = " + ans);

			}
			
			// 남은 자신보다 크거나 같은 사람들
			if (!stack.isEmpty()) {
				if (stack.peek().height == arr[j]) { // 같은 키
					ans += stack.peek().pairNum;
					tmpNum = stack.peek().pairNum + 1;
					if (stack.size() > 1)
						ans++;
					stack.pop();
//	                System.out.println("같은 키 처리: " + stack.pop() + ", ans = " + ans + ", tmpCnt = " + tmpNum);

				} else {  // 자신보다 큰 사람
					ans++;
//	                System.out.println("큰 사람 처리: ans = " + ans);

				}
			}
			stack.push(new Person(arr[j], tmpNum));
//	        System.out.println("푸시 후 스택: " + stack);

		}
		System.out.println(ans);
	}
}
This post is licensed under CC BY 4.0 by the author.