1912-s2 성공

This commit is contained in:
sm4640
2026-03-28 01:42:09 +09:00
parent a1c9fe6798
commit f79594f871

View File

@@ -0,0 +1,55 @@
# 연속합
import sys
input = sys.stdin.readline
def solution():
n = int(input().rstrip())
lst = [0]+list(map(int, input().rstrip().split()))
prefix_sum = [0] * (n+1)
min_lst = [0]*(n+1)
prefix_sum[0] = 0
min_lst[0] = 0
now_min = 0
for i in range(1, n+1):
prefix_sum[i] = prefix_sum[i-1] + lst[i]
min_lst[i] = now_min
now_min = min(now_min, prefix_sum[i])
result = float('-inf')
for i in range(1, n+1):
result = max(result, prefix_sum[i]-min_lst[i])
print(result)
return
solution()
"""
걸린 시간: 30분
시간 복잡도: 모든 계산과 반복은 O(n)에 끝난다.
해설: 연속된 부분합을 편하게 다루기 위해 prefix_sum을 생각하였다.
그 후 prefix_sum들을 살펴보니, 모든 prefix_sum에 대해서 그 앞에 있는 것들 중 제일 작은 prefix_sum 빼면 최대가 나올 것 같았다.
그럼 그 구간의 제일 작은 것들을 매번 찾을 수는 없으니, prefix_sum을 계산하면서 제일 작은 것을 기록해야겠다고 생각했다.
그렇게 되면 계속 O(n)으로 다 처리할 수 있다.
제일 작은 것을 기록하려다보니 계산된 prefix_sum 중에 작은 것을 기록하려고 했는데, 사실 계산된 prefix_sum이 음수가 아닌 이상, 제일 작은 것은 0이 맞다.
따라서 계산된 prefix_sum 이전에 0을 넣고, 쭉 계산을 진행했다.
마지막 반복문으로 result를 모든 prefix_sum에 대해 그 구간의 최소값을 빼보며 result의 최대값을 구했다.
이 논리를 좀 더 직관적으로 말하는 풀이법이 있는 kadane라는 것이다.
dp[i]를 볼때 i번째 숫자로 새로 시작할지, 기존 최적 수열에 i를 붙일지 선택하는 것이다.
lst[i] > dp[i] + lst[i]라는 뜻은 지금까지 최선을 다해온 팀이 있는데, 내가 들어가는 것보다 나 혼자 시작하는게 더 나은 경우이다.
lst[i] < dp[i] + lst[i]라는 뜻은 내가 너무 멍청해서 팀원들이 플러스 역할을 해준다는 경우이다.
이 나혼자 새로 시작한다는 시점이 바로 내 풀이의 now_min이 바뀌는 시점이다. 너무 벌레를 만나서 그 벌레를 끊고 이후부터 새로 시작했다는 뜻이다.
여기서도 result를 계속 max값 업데이트를 해줘야하는데 관계를 끊고 새로 시작했다고 해도, 어떤 팀들은 이미 최고의 플레이를 했을 수도 있기 때문이다.
"""