题目大意:
从一个数列a中抽出子数列,这个子数列的元素的原来的下标之间的间距小于k,现在问我们应该怎么抽出子数列使得抽出的数列的和最大。
解题思路:
很明显的,我们设置dp[i]为我们在a中抽出这个元素后,在[0,i]位置产生的最大子序列和。那么转移为:
其中range_max(i)表示我们在[i-k+1,i]中的最大子序列和。这句话的意思就是:我可以就此不继续生成子序列,或者我们想生成的话,必须转移到 最大位置。这里我们可以用单调队列优化得到range_max的值。
class Solution {
public:
int constrainedSubsetSum(vector<int>& nums, int k) {
int n = nums.size();
deque<int> dq;
vector<int> dp(n,0);
int ls = 0;
int ret = -1e9;
for(int i = 0;i<n;i++){
dp[i] = nums[i];
dp[i] = max(dp[i],dp[i] + ls);
while(dq.size() && dp[dq.back()]<dp[i])dq.pop_back();
if(dq.size() && dq.front() < i - k +1)dq.pop_front();
dq.push_back(i);
ls = dp[dq.front()];
ret = max(dp[i],ret);
}
return ret;
}
};