
12764 BOJ
문제
현재 대한민국 해군에 소속되어있는 준하는 문제를 풀기 위해 매일같이 사이버 지식 정보방 통칭 싸지방에 다닌다. 그러나 최근 문제가 생겼다. 싸지방에 사람이 몰려 컴퓨터 수가 모자라게 된 것이다. 이런 사태를 도저히 용납할 수 없었던 준하는 곧 전역하는 선임을 설득해 민원을 넣도록 하는 데 성공했다.
마침내 부대에서는 민원을 받아들이기로 하였고, 컴퓨터를 증설하기로 했다. 또한, 컴퓨터 간의 사용률에 따라 다른 성능의 컴퓨터를 설치하고자 한다.
하지만 예산이 부족해 사람 수 만큼 컴퓨터를 살 수가 없었다. 고심에 고심을 거듭한 준하는 모든 사람이 항상 정해진 시간에 싸지방을 이용한다는 사실을 발견했다.
컴퓨터가 있는 자리에는 1번부터 순서대로 번호가 매겨져 있다. 모든 사람은 싸지방에 들어왔을 때 비어있는 자리 중에서 번호가 가장 작은 자리에 앉는 것이 규칙이다.
준하가 발견한 사실과 이용 규칙을 가지고, 모든 사람이 기다리지 않고 싸지방을 이용할 수 있는 컴퓨터의 최소 개수와 자리별로 몇 명의 사람이 사용했는가를 구하시오.
접근
우선순위 큐를 세개 이용하여 해결하였다. 사용자에 대하여 먼저 온 순서대로 처리하기 위해, 아직 사용 중인 컴퓨터 중 사용가능한 것을 추리기 위해, 사용가능한 것들 중 가장 빠른 번호의 것을 선택하기 위해 우선순위 큐가 필요했다.
입력으로 주어지는 사용 정보가 정렬되어 들어오는 것이 아니기 때문에, 우선순위큐를 이용하여 빨리 입장하는 순서대로 처리하게 해준다.
아직 사용 중인 컴퓨터 중 현재 들어온 사용자의 입장 시간보단, 사용 종료 시간이 느린 컴퓨터도 있을 수 있다. 이러한 컴퓨터들을 사용가능한 컴퓨터들의 집합으로 옮겨주어야 한다. 사용 종료 시간 순으로 정렬되어 있어야 옮기는 작업이 빠르게 끝나기 때문에 우선순위 큐를 하나 생성해 사용한다.
사용 가능한 컴퓨터들 중 번호가 빠른 컴퓨터를 먼저 사용해야 한다. 번호가 빠른 컴퓨터를 고르기 위한 우선순위 큐를 하나 생성해 사용한다.
입력
첫째 줄에 사람의 수를 나타내는 (N)이 주어진다. ((1 \le N \le 100,000)) 둘째 줄부터 (N)개의 줄에 걸쳐서 각 사람의 컴퓨터 이용 시작 시각 (P)와 종료 시각 (Q)가 주어진다. ((0 \le P \lt Q \le 1,000,000))
시작 시각이나 종료 시각이 다른 사람과 겹치는 경우는 없다.
출력
첫째 줄에 사람이 모든 사람이 기다리지 않아도 되는 컴퓨터의 최소 개수 (X)를 출력한다.
둘째 줄에는 1번 자리부터 (X)번 자리까지 순서대로 각 자리를 사용한 사람의 수를 띄어쓰기 간격으로 출력한다.
코드
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef const ll cll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<vll> vvll;
typedef vector<vpll> vvpll;
typedef queue<ll> qll;
typedef queue<pll> qpll;
typedef priority_queue<ll> pqll;
typedef priority_queue<pll> pqpll;
typedef priority_queue<ll, vll, greater<ll>> pqgll;
typedef priority_queue<pll, vpll, greater<pll>> pqgpll;
#define FOR1(a, A) for (ll a = 0; a < A; ++a)
#define FOR2(a, b, A, B) \
for (ll a = 0; a < A; ++a) \
for (ll b = 0; b < B; ++b)
cll N = 1e5;
ll n, nseats[N] = {}, nseat = 1;
pqgpll users, nonavail;
pqgll avail;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
for (ll p, q, i = 0; i < n; ++i) {
cin >> p >> q;
users.push(make_pair(p, q));
}
avail.push(0);
while (!users.empty()) {
ll p = users.top().first, q = users.top().second;
users.pop();
while (!nonavail.empty() && nonavail.top().first <= p) {
avail.push(nonavail.top().second);
nonavail.pop();
}
if (avail.empty()) {
avail.push(nseat++);
}
++nseats[avail.top()];
nonavail.push(make_pair(q, avail.top()));
avail.pop();
}
cout << nseat << "\n";
for (ll i = 0; i < nseat; ++i) {
cout << nseats[i] << " ";
}
return 0;
}