diff --git a/workbook_7319/silver/1912-s2.py b/workbook_7319/silver/1912-s2.py new file mode 100644 index 0000000..5e69986 --- /dev/null +++ b/workbook_7319/silver/1912-s2.py @@ -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값 업데이트를 해줘야하는데 관계를 끊고 새로 시작했다고 해도, 어떤 팀들은 이미 최고의 플레이를 했을 수도 있기 때문이다. +""" \ No newline at end of file