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

이번 문제는 디제이맥스(DJMAX) 게임의 랭킹 리스트에 새로운 점수를 추가할 때, 그 점수가 랭킹 리스트에서 몇 등인지 결정하는 문제입니다. 주어진 랭킹 리스트는 비오름차순(내림차순으로 정렬)으로 정렬되어 있으며, 동일한 점수가 있을 경우 가장 작은 등수를 공유합니다. 새로운 점수가 랭킹 리스트에 들어갈 수 있는지 여부를 판단하고, 들어갈 수 있다면 그 등수를 출력하며, 들어갈 수 없을 경우 -1을 출력합니다.
N이 최대 랭킹 리스트 크기 P와 같은 경우), 새로운 점수가 마지막 점수보다 클 때만 리스트에 추가할 수 있습니다.1을 출력합니다.N, 새로운 점수 new_score, 랭킹 리스트의 최대 크기 P가 주어집니다.10 ≤ P ≤ 50, 0 ≤ N ≤ PN개의 점수가 비오름차순으로 주어집니다. (N > 0인 경우에만)0 ≤ score ≤ 2,000,000,000예제 입력 1:
3 90 10
100 90 80
예제 출력 1:
2
해석:
[100, 90, 80]90P=10이므로, 새로운 점수를 추가할 수 있습니다.[100, 90, 90, 80]90은 두 번째 위치에 삽입되므로, 등수는 2입니다.예제 입력 2:
10 1 10
10 9 8 7 6 5 4 3 2 1
예제 출력 2:
-1
해석:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]11은 마지막 점수 1과 같으므로 추가할 수 없습니다.1입니다.예제 입력 3:
10 1 10
10 9 8 7 6 5 4 3 3 0
예제 출력 3:
10
해석:
[10, 9, 8, 7, 6, 5, 4, 3, 3, 0]11은 마지막 점수 0보다 크므로 추가할 수 있습니다.[10, 9, 8, 7, 6, 5, 4, 3, 3, 1]1은 마지막 위치에 삽입되므로, 등수는 10입니다.예제 입력 4:
0 0 50
예제 출력 4:
1
해석:
0을 추가하면, 리스트는 [0]이 되며, 등수는 1입니다.이 문제는 새로운 점수를 랭킹 리스트에 추가할 수 있는지 판단하고, 추가할 수 있다면 그 점수가 몇 등인지 계산하는 문제입니다. 이를 효율적으로 해결하기 위해 다음과 같은 접근 방식을 사용합니다:
N, 새로운 점수 new_score, 랭킹 리스트의 최대 크기 P를 입력받습니다.N개의 점수를 비오름차순으로 입력받습니다.N=0):1입니다.N < P):N = P):1을 출력합니다.아래는 위의 접근 방식을 구현한 파이썬 코드입니다.
import sys
def main():
import sys
input = sys.stdin.readline
# 첫 번째 줄: N, new_score, P
first_line = ''
while first_line.strip() == '':
first_line = input()
parts = first_line.strip().split()
N = int(parts[0])
new_score = int(parts[1])
P = int(parts[2])
# 두 번째 줄: N개의 점수 (비오름차순), N >0인 경우에만
scores = []
if N > 0:
second_line = ''
while len(scores) < N:
second_line = input()
if not second_line:
break
parts = second_line.strip().split()
scores += list(map(int, parts))
# Ensure we have exactly N scores
scores = scores[:N]
# 함수: 새로운 점수의 등수를 찾는 함수
def find_rank(scores, new_score):
for i, score in enumerate(scores):
if new_score > score:
return i + 1
elif new_score == score:
return i + 1
return len(scores) + 1
# 랭킹 리스트가 꽉 차지 않은 경우
if N < P:
# 랭킹 리스트에 새로운 점수를 추가
# Find the rank
rank = find_rank(scores, new_score)
print(rank)
else:
# 랭킹 리스트가 꽉 찬 경우
# Check if new_score > last score
if new_score > scores[-1]:
# Insert the new_score and remove the last score
# Find the rank
rank = find_rank(scores, new_score)
print(rank)
else:
# 새로운 점수를 추가할 수 없음
print(-1)
if __name__ == "__main__":
main()
# 첫 번째 줄: N, new_score, P
first_line = ''
while first_line.strip() == '':
first_line = input()
parts = first_line.strip().split()
N = int(parts[0])
new_score = int(parts[1])
P = int(parts[2])
# 두 번째 줄: N개의 점수 (비오름차순), N >0인 경우에만
scores = []
if N > 0:
second_line = ''
while len(scores) < N:
second_line = input()
if not second_line:
break
parts = second_line.strip().split()
scores += list(map(int, parts))
# Ensure we have exactly N scores
scores = scores[:N]
N, 새로운 점수 new_score, 랭킹 리스트의 최대 크기 P를 입력받습니다.N개의 점수를 입력받아 scores 리스트에 저장합니다.while 루프를 사용하여 필요한 만큼 반복적으로 입력을 받습니다.scores 리스트가 정확히 N개의 점수를 가지도록 잘라줍니다.def find_rank(scores, new_score):
for i, score in enumerate(scores):
if new_score > score:
return i + 1
elif new_score == score:
return i + 1
return len(scores) + 1
scores 리스트와 new_score를 인자로 받아, 새로운 점수가 리스트 내에서 몇 등인지 계산합니다.new_score가 현재 점수보다 클 경우 그 위치가 새로운 점수의 등수가 됩니다.new_score가 현재 점수와 같을 경우, 그 위치가 새로운 점수의 등수가 됩니다.new_score가 가장 낮다면, len(scores) + 1을 반환합니다.# 랭킹 리스트가 꽉 차지 않은 경우
if N < P:
# 랭킹 리스트에 새로운 점수를 추가
# Find the rank
rank = find_rank(scores, new_score)
print(rank)
else:
# 랭킹 리스트가 꽉 찬 경우
# Check if new_score > last score
if new_score > scores[-1]:
# Insert the new_score and remove the last score
# Find the rank
rank = find_rank(scores, new_score)
print(rank)
else:
# 새로운 점수를 추가할 수 없음
print(-1)
N < P):find_rank 함수를 호출하여 새로운 점수의 등수를 계산하고 출력합니다.N = P):find_rank 함수를 호출하여 새로운 점수의 등수를 계산하고 출력합니다.1을 출력합니다.예제 입력 1:
3 90 10
100 90 80
실행 과정:
N=3, new_score=90, P=10scores = [100, 90, 80]N < P이므로, find_rank(scores, 90) 호출i=0, score=100: 90 < 100 → 계속i=1, score=90: 90 == 90 → 등수 2 반환2예제 입력 2:
10 1 10
10 9 8 7 6 5 4 3 2 1
실행 과정:
N=10, new_score=1, P=10scores = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]N == P이므로, new_score=1과 scores[-1]=1 비교1 > 1 → 거짓1예제 입력 3:
10 1 10
10 9 8 7 6 5 4 3 3 0
실행 과정:
N=10, new_score=1, P=10scores = [10, 9, 8, 7, 6, 5, 4, 3, 3, 0]N == P이므로, new_score=1과 scores[-1]=0 비교1 > 0 → 참find_rank(scores, 1) 호출i=0, score=10: 1 < 10 → 계속i=1, score=9: 1 < 9 → 계속i=2, score=8: 1 < 8 → 계속i=3, score=7: 1 < 7 → 계속i=4, score=6: 1 < 6 → 계속i=5, score=5: 1 < 5 → 계속i=6, score=4: 1 < 4 → 계속i=7, score=3: 1 < 3 → 계속i=8, score=3: 1 < 3 → 계속i=9, score=0: 1 > 0 → 등수 10 반환10예제 입력 4:
0 0 50
실행 과정:
N=0, new_score=0, P=50scores = []N < P이므로, find_rank(scores, 0) 호출len(scores) + 1 = 1 반환1N과 P를 읽는 데 O(1)N개의 점수를 읽는 데 O(N)find_rank):find_rank 함수는 최대 N번 비교를 수행합니다.O(N)if N < P 조건에서 find_rank 호출 → O(N)else 조건에서 find_rank 호출 또는 1 출력 → O(N) 또는 O(1)O(N)N의 최대 값은 50이므로, 실제로는 매우 빠르게 동작합니다.scores):O(N)O(1)O(N)N의 최대 값이 50이므로, 공간 사용량은 매우 작습니다.제공된 파이썬 코드는 선형 탐색(Linear Search)을 사용하여, 새로운 점수가 랭킹 리스트 내에서 몇 등인지 효율적으로 계산합니다. 시간 복잡도는 O(N), 공간 복잡도는 O(N)으로, 주어진 문제의 제한 사항 (N ≤ 50) 내에서 매우 효율적으로 동작합니다.
O(N)O(N)이 접근 방식은 랭킹 리스트가 비교적 작고, 리스트 내에서의 순차적인 탐색이 필요한 상황에서 매우 효과적입니다. 또한, 동일한 점수가 있을 때 첫 번째 등수를 공유하는 요구 사항을 간단하게 만족시킬 수 있습니다.