※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 2790번 문제인 F7이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/2790 

 

2790번: F7

권위를 자랑하는 레이싱 대회 F7이 열릴 예정이다. F7은 드라이버의 순위가 자주 바뀌기 때문에 사람들에게 인기가 아주 많다. 상근이는 F7 레이싱의 엄청난 팬이지만, 마지막 레이싱과 중간고사

www.acmicpc.net

어떤 드라이버가 우승하기 좋은 최적의 경우는 (1) 그 드라이버가 1등을 하고 (2) 남은 드라이버들의 현재 점수의 역순으로 2등부터 N등까지 하는 것이다. 이 상황이 왔을 때 해당 드라이버가 우승을 할 수 있는지를 판단해 문제를 해결하자. 다만 이를 단순히 구현하기에는 입력의 크기가 크므로 효율적인 방법을 생각해보자.

 

먼저 주어진 드라이버들의 점수를 오름차순으로 정렬하자. 이 때 어떤 드라이버가 우승할 수 있는지를 판단하려면 이 배열에서 그 드라이버는 N점을, 남은 드라이버들은 차례대로 점수를 N-1 ~ 1점씩 받은 경우만을 생각하면 된다. 각 드라이버가 받을 점수는 어떤 드라이버를 고르더라도 고른 드라이버의 왼쪽인지 오른쪽인지에 따라서만 달라짐을 관찰하자.

 

위의 관찰을 이용해, 각각의 드라이버를 골랐을 때 그 왼쪽의 드라이버들의 (마지막 경수 후의, 위에서같이 점수를 받은 다음의) 점수의 최댓값과 오른쪽의 드라이버들의 점수의 최댓값을 전처리하고 이를 이용해 해당 드라이버가 우승할 수 있는지를 판단해 문제를 해결하자. 이 전처리는 \(O(N)\)에 해낼 수 있다.

 

전체 문제 해결에 드는 시간복잡도는 배열의 정렬시간인 \(O(NlgN)\)이다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <algorithm>
using namespace std;

int N;
int arr[300000];
int maxL[300000], maxR[300000];
int ans;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N;
	for (int i = 0; i < N; i++) cin >> arr[i];
	sort(arr, arr + N);
	
	maxL[0] = arr[0] + N - 1;
	for (int i = 1; i < N; i++) maxL[i] = max(arr[i] + (N - 1) - i, maxL[i - 1]);
	
	maxR[N - 1] = arr[N - 1] + 1;
	for (int i = N - 2; i > -1; i--) maxR[i] = max(arr[i] + (N - i), maxR[i + 1]);

	if (arr[0] + N >= maxR[1]) ans++;
	for (int i = 1; i + 1 < N; i++) {
		if (maxL[i - 1] <= arr[i] + N && arr[i] + N >= maxR[i + 1]) ans++;
	}
	if (maxR[N - 2] < arr[N - 1] + N) ans++;

	cout << ans;
}
728x90

+ Recent posts