题面:https://codeforces.com/contest/1668/problem/D
大致题意:给定一个数列,随意划分该数列为非空子数列,规定子数列的值为:
- 子数列总和为正,则为其长度,即i-j+1
- 子数列总和为0,则为0
- 子数列总和为负,则为其长度的相反数
求数列子数列值总和的最大值
题解:设dp[i]为前i个元素的最大值,sum[i]为前i个元素的和,则dp[j]到dp[i]的状态转移为:
- dp[i]=dp[j-1]+i-j+1 (sum[i]-sum[j-1]>0)
- dp[i]=dp[j-1] (sum[j]=sum[i-1])
- dp[i]=dp[j-1]+j-i-1 (sum[i]-sum[j-1]<0)
故我们维护dp[i],每次需要向前遍历找最大值,时间复杂度为,糊不过这题
注意到找最大值时,i一定,故找dp[j-1]-(j-1)的最大值,因此我们想到用树状数组or线段树维护前i-1个元素的dp[j-1]-(j-1)的最大值(需要保证sum[i]-sum[j-1]>0)
问题:如何处理sum差的其他情况?
- 易知,对最终答案中的划分情况,我们可以将所有的非正子数列划分成长度为1的子数列而不影响结果,故我们将其考虑到状态转移方程中,即考虑a[i]的正负,通过dp[i-1]递推出dp[i]的可能值(注意dp[0]应为0)
因此,我们只需维护sum[i]-sum[j-1]>0且i>j的情况
用树状数组维护时,先统计前缀和大小,再根据前缀和的大小重新排序即可
1 |
|