E - アルバイトのシフト管理 / Part-Time Job Shift Management Editorial by admin
GPT 5.2 HighOverview
We construct a length-\(N\) sequence where each day is either “work (1)” or “rest (0)”, under the constraints that consecutive working days are at most \(K-1\) and consecutive rest days are at most \(M-1\), and we maximize the total salary earned on working days.
Analysis
Key Observation
The constraints only determine the maximum length of consecutive identical states (work/rest), so the optimal solution can be computed by transitions that only look at the “most recent switching position”: - “From the last rest day” to “working consecutively until today” - “From the last working day” to “resting consecutively until today”
Why a Naive DP Doesn’t Work
For example, if we define: - \(dp[i][x][c]\) = maximum value when looking at the first \(i\) days, where state \(x\in\{0,1\}\) has continued for \(c\) consecutive days
then the number of states becomes \(O(N(K+M))\), which is far too slow for \(N\le 2\times 10^5\).
How to Solve It
Instead of explicitly tracking the “consecutive length”, we only maintain: - \(dp1[i]\): maximum value when the last day is a working day - \(dp0[i]\): maximum value when the last day is a rest day
and enumerate the “most recent switching day \(p\)” in the transitions.
However, as-is: - \(dp1[i]\) requires the maximum over \(p\in[i-K+1,\,i-1]\) - \(dp0[i]\) requires the maximum over \(p\in[i-M+1,\,i-1]\)
which results in \(O(NK)\) or \(O(NM)\) complexity.
Therefore, we manage the “sliding window maximum” using a monotonic deque, processing each \(i\) in amortized \(O(1)\).
Algorithm
DP Definition
When the first \(i\) days (\(1\sim i\)) have been decided: - \(dp1[i]\): maximum salary when day \(i\) ends with work - \(dp0[i]\): maximum salary when day \(i\) ends with rest
As an initial state, we prepare “day 0”: - \(dp0[0]=0,\ dp1[0]=0\)
(This naturally handles both starting with work and starting with rest.)
Impossible states are set to \(-\infty\) (in the code, INF_NEG).
Transition (Ending with Work)
If day \(i\) ends with work, let \(p\) be the last day that ended with rest: - Days \(p+1, p+2, \dots, i\) are consecutive working days - The consecutive working days constraint \(i-p \le K-1\) gives \(p \ge i-K+1\) - At least 1 consecutive working day, so \(p \le i-1\)
Therefore: [ dp1[i] = \max{p\in[i-K+1,\,i-1]} \left(dp0[p] + \sum{t=p+1}^{i} A_t\right) ]
Using the prefix sum \(pref[i]=\sum_{t=1}^{i}A_t\): [ \sum_{t=p+1}^{i} A_t = pref[i]-pref[p] ]
So: [ dp1[i] = pref[i] + \max_{p\in[i-K+1,\,i-1]} \left(dp0[p]-pref[p]\right) ]
This transforms the problem into finding the “maximum value in an interval”.
Transition (Ending with Rest)
Similarly, if day \(i\) ends with rest, let \(p\) be the last day that ended with work: - Days \(p+1,\dots,i\) are consecutive rest days - The constraint \(i-p \le M-1\) gives \(p \ge i-M+1\) - At least 1 consecutive rest day, so \(p \le i-1\)
Therefore: [ dp0[i] = \max_{p\in[i-M+1,\,i-1]} dp1[p] ]
Speedup: Maintaining “Sliding Maximum” with a Monotonic Deque
We need the following two “sliding window maximums”:
For \(dp1[i]\): the maximum of [ X[p]=dp0[p]-pref[p] ] over the interval \(p\in[i-K+1,\,i-1]\) → Managed by deque
D1(maintaining values in decreasing order)For \(dp0[i]\): the maximum of [ dp1[p] ] over the interval \(p\in[i-M+1,\,i-1]\) → Managed by deque
D0(maintaining values in decreasing order)
For each day \(i\): - Remove elements from the front of the deque that are outside the interval (index smaller than the left endpoint) - The front of the deque is the maximum value for that interval - Add the new candidate (value at index \(i\)) by removing smaller elements from the back
Since each index is added and removed from the deque at most once, the total complexity is \(O(N)\).
Finally, the answer allows day \(N\) to be either work or rest, so: [ \max(dp0[N], dp1[N]) ]
is the maximum salary. If both are impossible, output -1.
Complexity
- Time complexity: \(O(N)\) (each index enters/exits the deque at most once)
- Space complexity: About \(O(K+M)\) (the number of elements held in the deque is proportional to the window width, at most \(O(N)\))
Implementation Notes
To represent impossible states, a sufficiently small value is used (
INF_NEG=-10**30in the code), and before adding to the deque, we check whether the state is reachable.The most crucial transformation is rewriting the formula for \(dp1[i]\) as: [ dp1[i]=pref[i]+\max(dp0[p]-pref[p]) ] which reduces it to a “range maximum” problem.
The left endpoint of the interval, \(i-K+1\) or \(i-M+1\), can become negative, so it is clamped to \(0\) (
L1,L0in the code).Source Code
import sys
from collections import deque
INF_NEG = -10**30
def push_max(deq, idx, val):
while deq and deq[-1][1] <= val:
deq.pop()
deq.append((idx, val))
def main():
input = sys.stdin.readline
N, K, M = map(int, input().split())
A = list(map(int, input().split()))
# D1: for dp1[i] = pref[i] + max(dp0[p] - pref[p]) over p in [i-K+1, i-1]
# D0: for dp0[i] = max(dp1[p]) over p in [i-M+1, i-1]
D1 = deque()
D0 = deque()
push_max(D1, 0, 0) # dp0[0] - pref[0]
push_max(D0, 0, 0) # dp1[0]
pref = 0
dp0_i = 0
dp1_i = 0
for i in range(1, N + 1):
pref += A[i - 1]
L1 = i - K + 1
if L1 < 0:
L1 = 0
L0 = i - M + 1
if L0 < 0:
L0 = 0
while D1 and D1[0][0] < L1:
D1.popleft()
while D0 and D0[0][0] < L0:
D0.popleft()
dp1_i = pref + (D1[0][1] if D1 else INF_NEG)
dp0_i = (D0[0][1] if D0 else INF_NEG)
if dp0_i > INF_NEG // 2:
push_max(D1, i, dp0_i - pref)
if dp1_i > INF_NEG // 2:
push_max(D0, i, dp1_i)
ans = max(dp0_i, dp1_i)
if ans <= INF_NEG // 2:
print(-1)
else:
print(ans)
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.2-high.
posted:
last update: