2020杭电多校第八场 1002 HDU 6856 Breaking Down News 线段树+单调队列+dp
题意:给出一个由{-1,0,1}中元素组成的长度为n的序列,将其分为若干段,且任意段长度len(i)满足 L<=len(i)<=R,每段数字和记作w,则每段价值为w/abs(w)或0,求最大总价值
n,L,R<1e6
题解:考虑dp,记\(f[i]\)表示前i个数字分成若干区间得到的最大答案。因为以i为结尾的最后一个区间左端点肯定在\([i-R+1,i-L+1]\)之间,所以\(f[i]\)只能从\(f[i-R]到f[i-L]\)转移过来。
转移方程为:\(f[i]=max\{f[j]+(s[j]>s[i])-(s[i]<s[j]),j∈[i-L,i-R]\}\)
上式中,难以解决的是后面的大小判断的值,但是如果我们对前缀和进行排序,建立s的权值线段树,每次求f[i]时,可以分三种情况讨论,一种是从满足\(s[j]<s[i]\)的所有\(j\)中的最大\(f[j]\)转移过来,这种情况下转移式中判断的值就为1了,所以只要找到了这样的\(j'\),就有\(f[i]=f[j']+1\)。同理,其他两种是\(f[j']=max(f[j]),s[j]==s[i],f[i]=f[j']\),\(f[j']=max(f[j]),s[j]>s[i],f[i]=f[j']-1\)
如何维护最大的\(f[j]\),又要满足\(i-L<=j<=i-R\),这时候就要用到单调队列了!给线段树的每个叶子节点都建一个单调队列,维护相同值的一个从队首到队尾单调不增的队列,每次枚举到i,要把对应的\(f[i-L]\)加入单调队列,同时在更新完\(f[i]\)后删除\(f[i-R]\)。
最后还有一个问题,怎么建树呢,由于序列中只有{-1,0,1}三种值,可以知道,极端情况下最小的前缀和是\(-n\),最大前缀和为\(n\),根据这一点,可以先找出最小前缀和\(mn\),其他所有的前缀和肯定都不超过\(mn+n\),所以可以建一棵值为相对\(mn\)大小的权值线段树,s[i]对应的相对位置为\(s[i]-mn\),这其实也就是它对应的叶子节点的权值。
这样一来,判断有无解,只需要看\(f[n]\)和\(-n\)的大小关系了。

浙公网安备 33010602011771号