Problem Description
Given an integer array nums and a list of queries where each query updates an element in nums, after each update you must compute the maximum sum that can be obtained by selecting a subsequence such that no two chosen elements are adjacent. (An empty subsequence is allowed, which gives a sum of 0.) Return the sum of the answers for all queries modulo 10^9+7.
Key Insights
- This is the “House Robber” style problem but with dynamic updates.
- A naïve re‐computation via dynamic programming for each query would be O(n) per query, which is too slow.
- We can design a segment tree where each node stores enough DP information so that segments can be merged quickly.
- By formulating each index as a “segment” that gives two outcomes depending on whether you are allowed to choose that element (if the previous element was not chosen) or forced to skip it (if the previous element was chosen), we can merge segments via a “DP transition.”
- Merging two segments is analogous to “matrix multiplication” – for a given starting state (allowed vs. not allowed) we try both possibilities for the ending state of the left segment and use that as input for the right segment.
Space and Time Complexity
Time Complexity: O((n + q) * log n), where n is the size of nums and q is the number of queries (each update takes O(log n)). Space Complexity: O(n) for the segment tree.
Solution
We solve the problem by modeling the non-adjacent subsequence selection as a DP that works on intervals. For each index i we consider two states:
- State 0 (free): the previous element was not selected so we can decide to pick nums[i] (if it is beneficial) or skip it.
- State 1 (forced skip): the previous element was selected, so we must skip the current element.
For each element, we build a 2×2 DP “transition matrix” T such that: • T[0][0] = 0 means that if we are allowed to pick and we skip the element, we add 0. • T[0][1] = nums[i] if nums[i] > 0 (or –∞ if nums[i] is negative) which represents picking the element. • T[1][0] = 0 because when forced to skip, the only option is to skip. • T[1][1] = –∞ since you cannot pick when forced.
We denote –∞ as a very small number (e.g. MIN = -10^18) to ensure we never choose invalid transitions.
To merge two segments (with matrices A and B), the new transition matrix V is computed as: V[s][t] = max( A[s][r] + B[r][t] ) for r in {0, 1}, and for every starting state s and ending state t. The overall answer for the current nums array after a query is then: max( TreeRoot[0][0], TreeRoot[0][1] ) (using 0 as the initial “free” state because no element precedes index 0).
A segment tree is built with these matrices at its leaves and uses our merge function at internal nodes. On each query, we update one leaf in O(log n) time and then read the result at the tree’s root.