rt。求助,大佬们~
如果必须对a求解,目前还没想到好的方法。但是如果可以选择a任意长度的前缀求解,则有O(nlognlogV)的方法。
设 fi 为 a1∼i 最多可以分多少段,使得每段的和都 ≤mid。
则有转移 fi,j=max(fj+1),其中 j 满足 j<i,Si−Sj≤mid(S 是 a 的前缀和数组)。
如果存在 fi≥m,则说明合法,这是因为如果fi>m,则必定存在j<i,使得fj=m。
这里也是为什么难以只对a求解,因为有负值所以不满足单调性(即fi合法⇏fi+1也合法),因此如果定义f为最大分段数则只能求得a所有前缀的答案,如果要仅求a的答案,必须将f所有可能的取值都计算出来,这样还得再乘一个O(n)。
这样时间复杂度是 O(n2logV),时间开销主要再 O(n) 的转移,考虑优化。
Si−Sj≤mid⟺Sj≥Si−mid。我们考虑用 Su 作为索引,fu 作为值,扔到线段树里。
更新的时候求线段树 (Si−mid)∼V 的最大值 maxx,用 maxx+1 更新 fi 即可。
因为 V 太大,所以要将所有用到的下标(即 Si 和所有 Si−mid)离散化。
时间复杂度降至 O(nlognlogV)。
也可以用树状数组代替线段树,虽然树状数组无法维护区间最大值,但是每次询问的区间都是一个后缀,所以只需要反向建立树状数组即可,码量和速度上都优于线段树。
线段树实现:https://paste.ubuntu.com/p/NKCTF6TVkK/
树状数组实现:https://paste.ubuntu.com/p/wsBNqzgtxf/