※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 28284번 문제인 스터디 카페이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/28284
28284번: 스터디 카페
주원이는 스터디 카페를 운영하고 있다. 스터디 카페에는 $N$개의 좌석이 있으며, $i$번째 좌석의 하루 요금은 $A_i$이다. 주원이는 최근에 새로운 아르바이트생을 고용했는데, 아르바이트생에게
www.acmicpc.net
벌 수 있는 최대 수익은 각 날에 스터디 카페에 찾아온 이용자 K명을 비용이 비싼 차례대로 K개의 좌석에 앉힐 때임을 쉽게 알 수 있다. 다만 모든 날에 대하여 이를 시뮬레이션하는 것으로는 문제를 충분히 해결할 수 없다. 10억일동안의 각 날에 대해 직접 계산하기에는 제한시간이 부족하기 때문이다.
위의 문제를 효율적으로 해결하기 위해 스터디 카페에 찾아오는 인원이 바뀌는 날들을 기준으로 기간을 나누는 방법을 생각하자. 이와 같이 나눌 경우, 각 나눠진 기간에 벌 수 있는 최대 수익은 (기간에 포함된 날의 수) * (해당 기간의 각 날에 벌 수 있는 최대 수익)과 같이 구할 수 있음은 쉽게 관찰할 수 있다. 또한 하루의 최대 수익은 그 날 찾아오는 인원이 정해지면 변하지 않으므로 prefix sum을 이용해 전처리해 두면 프로그램을 빠르게 동작하게 할 수 있다.
최소 비용 또한 비슷한 방법으로 구해 문제를 해결하자.
문제의 답이 32비트 정수 자료형으로 표현할 수 있는 범위를 넘을 수 있음에 유의하자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int N, M;
ll cost1[500000], cost2[500000];
ll oldT, curcost; int cidx = -1;
vector<pair<ll, int>> sched;
ll ans1, ans2;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
for (int i = 0; i < N; i++) cin >> cost1[i];
sort(cost1, cost1 + N, greater<>());
for (int i = 0; i < N; i++) cost2[i] = cost1[N - i - 1];
for (int i = 1; i < N; i++) cost1[i] += cost1[i - 1];
for (int i = 1; i < N; i++) cost2[i] += cost2[i - 1];
while (M--) {
int S, E; cin >> S >> E;
sched.emplace_back(make_pair(S, 1));
sched.emplace_back(make_pair(E + 1, -1));
}
sort(sched.begin(), sched.end());
for (auto& p : sched) {
if (cidx >= 0) ans1 += (p.first - oldT) * cost1[cidx], ans2 += (p.first - oldT) * cost2[cidx];
oldT = p.first;
cidx += p.second;
}
cout << ans2 << ' ' << ans1;
}
'BOJ' 카테고리의 다른 글
[BOJ 28282 // C++] 운명 (1) | 2023.11.21 |
---|---|
[BOJ 28283 // C++] 해킹 (1) | 2023.11.20 |
[BOJ 28285 // C++] 육각형 순회 (0) | 2023.11.18 |
[BOJ 6844 // C++] Keep on Truckin' (0) | 2023.11.17 |
[BOJ 6842 // C++] Deal or No Deal Calculator (0) | 2023.11.16 |