전구의 밝기들이 배열로 주어지고, 초기에 켜져있는지, 꺼져있는지가 주어진다.
연속하는 구간내의 모든 전구들의 상태를 뒤집으면 켜진 전구는 꺼지고, 꺼진 전구는 켜진다.
이 연산을 정확히 1번 해야할때, 전구 밝기들의 합의 최댓값을 구한다.
----------------------------------------------------------------------------------------------------------------------------------------------------
n이 최대 20만인데, 연속하는 구간의 상태를 뒤집어야한다?
구간 dp로 하자니 O(N^2)일텐데
그리고 연산을 무조건 1번은 해야한다는거까지
굉장히 어렵다
처음 상태에서 밝기 합을 S라고 하고, 전구 상태를 바꿀때, 밝기의 변화량을 D라고 한다.
예를 들어 A = [2,3,5], B = [1,0,1]이라고 한다면, 전구 상태를 바꾸면 켜져있는 전구는 꺼지므로
밝기가 -가 되어야하고, 꺼져있는 전구는 켜지므로 밝기가 +가 되어야한다.
D = [-2,3,-5]가 된다.
그러면 연속하는 구간의 전구를 뒤집는다는 것은 무엇을 의미하는가?
최초 밝기 상태 S에서 어떤 구간 [i,j]내의 전구들의 상태를 바꾼다면, S에서 [i,j]내의 원소들을 빼거나 더하는 것이다.
즉, 켜진 상태였다면 S에서 빼줘야하고, 꺼진 상태였다면 S에서 더해줘야하고
그러므로 S + ([i,j]내의 빼거나 더하는 양의 최댓값)이 정답이 된다.
그런데 ([i,j]내의 빼거나 더하는 양의 최댓값) 이 값은?
D배열에서 연속하는 구간내 원소 합의 최댓값과 같다.
이는 카데인 알고리즘을 이용하면 O(N)에 구할 수 있음이 알려져있다
https://deepdata.tistory.com/390
다이나믹 프로그래밍 - Kadane algorithm
1. 문제 https://www.acmicpc.net/problem/1912 1912번: 연속합첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거
deepdata.tistory.com
n = int(input())
A = list(map(int,input().split()))
B = list(map(int,input().split()))
s = 0
D = []
for i in range(n):
if B[i] == 1:
s += A[i]
D.append(-A[i])
else:
D.append(A[i])
INF = 10**18
dp = [-INF]*n
dp[0] = D[0]
for i in range(1,n):
dp[i] = max(dp[i-1] + D[i], D[i])
print(s + max(dp))
'알고리즘 > 다이나믹 프로그래밍' 카테고리의 다른 글
양팔저울을 이용해서 무게를 알아낼 수 있는 추를 찾는 방법 (0) | 2025.04.04 |
---|---|
배열을 뒤집어서 다른 배열과 대응하는 원소끼리 곱의 합의 특징 (0) | 2025.04.03 |
한번 쉬면 끝까지 쉬어야할 때 최대한 멀리 달리는 다이나믹 프로그래밍 (0) | 2025.03.19 |
길이가 K인 증가하는 부분 수열의 개수를 구하는 다이나믹 프로그래밍 (0) | 2025.03.11 |
크기가 1씩 증가하는 가장 긴 증가하는 부분수열의 길이를 구하는 다이나믹 프로그래밍 (0) | 2025.03.10 |