halang-log
💡 PS

[BOJ] 25635 자유 이용권

date
May 28, 2024
slug
boj-25635
author
status
Public
tags
PS
그리디
summary
자유 이용권 문제 풀이
type
Post
thumbnail
category
💡 PS
updatedAt
May 28, 2024 03:15 PM
언어
Java/C/C++/C#

문제

풀이

놀이기구의 종류의 개수 N과 ai(i번째 놀이기구 이용 횟수)가 주어진다. 문제를 풀기 전에 간단한 사실부터 짚고 가자.
 
아래와 같이 1이라는 숫자가 5개 있다고 해보자. 같은 숫자끼리 인접할 수 없으므로, 노랑색 형광펜이 칠해져 있는 곳에는 어떠한 숫자가 와야 한다.
notion image
 
여기서 “어떠한 숫자”는 1이 아닌, 아무 숫자나 와도 된다. 만약 노란 영역에 올 수 있는 숫자가 3개 밖에 없다면? 1은 다섯개가 있지만 정답으로 포함되는 숫자는 4개뿐이다.
 
놀이기구 이용 횟수 리스트가 주어졌을 때, 이를 오름차순으로 정렬하고 누적합을 만든다.
notion image
 
case. ix = 3
그리고 가장 큰 수부터 본다. 5개 중 몇개가 인정될 수 있는지 볼 것이다.
 
ix = 3이 아닌 다른 숫자들은 총 8개가 있다. 이는 누적합 배열에서 바로 확인 가능하다. 4개만 있으면 5개 모두 인정인데 이것보다 더 많으니 우선 ans는 5가 된다.
 
case. ix = 2
(idx 하나씩 줄어듦) 그 다음에도, 3개 중 몇개가 인정될 수 있는지 보자.
 
ix = 2 가 아닌 인정될 수 있는 다른 숫자들은 총 몇개인가? 누적합 배열만 보고 5라고 생각했으면 틀렸다. 지금까지 정답으로 누적한 값도 포함시켜야한다. 즉, ( 누적합 5 + ans 5 = 10) 이다.
2개만 있으면 2개 모두 인정인데 이것보다 더 많으니 ans는 5 + 3 = 8 이다.
 
case. ix = 1
그 다음에도, 3개 중 몇개가 인정될 수 있는지 보자.
 
ix = 1이 아닌, 인정될 수 있는 다른 숫자들은 누적합 배열에서 보이는 2와 ans 값을 합하여 10이다. 3보다 훨씬 크므로, ans는 8 + 3 = 11 이다.
 
case. ix = 0
그 다음은 2이다. 현재 2라는 숫자에서 몇개가 인정될 수 있는지 보자.
 
ix=0이 아닌, 인정될 수 있는 다른 숫자들은 누적합에서는 0이고, ans는 11이므로 11이다. 따라서 2 모두 인정된다.
 
위 예시에서의 정답은 11 + 2 = 13 이 된다.
 
위와 같은 로직대로 코드를 작성하면 된다.
 

코드

#include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int n; ll arr[100001]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%lld", &arr[i]); } sort(arr + 1, arr + n + 1); // 정렬하고 for(int i = 1; i <= n; i++) { // 누적합 계산 arr[i] += arr[i-1]; } ll ans = 0; // long long 타입인걸 주의하자 for(int i = n; i > 0; i--) { ll cur = arr[i] - arr[i-1] - 1; // 현재 필요한 개수 if (cur > arr[i-1] + ans) { // 필요한 개수보다 적으면 ans += arr[i-1] + ans + 1; // 최대로 할 수 있는 만큼만 더해주고 } else ans += arr[i] - arr[i-1]; // 아니면 다 해주기 } printf("%lld", ans); }