问题

给定序列aia_i和常数EE,问有多少种将其划分为若干非空段的方案,使得相邻两段的最小值至少相差EE

题解

fif_i表示,已经考虑a1aia_1\dots a_i的划分,且aia_i为其所在段的首个最小值,有多少合法划分方案(aia_i所在段可能还未闭合)。

考虑对于ii,哪些区间[l,r][l, r]满足aia_i是首个最小值

用单调栈预处理ii左侧第一个ai\le a_i的位置LiL_i,以及ii右侧第一个<ai< a_i的位置RiR_i

Li<lr<RiL_i < l \le r < R_i满足aia_i为其首个最小值

考虑哪些jj (j<ij < i) 可以用fjf_j贡献fif_i

  • ajaiEa_j \le a_i - E

  • ajai+Ea_j \ge a_i + E

第一类

ajaiEa_j \le a_i - E

考虑jjii之间有多少种可能的断点

依据我们对ii成为最小值的区间的观察,断点必须在LiL_i右边

又注意到这些jj显然满足jLij \le L_i

(Li,i](L_{i}, i]都可成为jj所在段与ii所在段的断点

对于一个jj,它在i(j,Rj)i \in (j, R_j)可能成为一个能对ii做贡献的jj

使用树状数组,维护对于目前ii可贡献的那些jj,以aja_j为下标的ff的前缀和

fi+(iLi)bit.query(aiE) f_i \leftarrow^{+} (i - L_i) * bit.query(a_i - E)

第二类

ajai+Ea_j \ge a_i + E

考虑jjii之间有多少种可能的断点

依据我们对jj成为最小值的区间的观察,断点必须在RjR_j左边

又注意到iRji \ge R_j

(j,Rj](j, R_{j}]都可以成为jj所在段和ii所在段的断点

aia_i必须是断点到ii这一段的最小值

fif_i从第二类jj获得的实际贡献contricontr_i,应为满足要求1.的所有jj对其的贡献之和jfj×(Rjj)\sum_j f_j \times (R_j - j) ,减去contrLicontr_{L_i}

如此一来便能抵消所有aia_i并非断点到ii这一段的最小值的情况下的非法贡献。

计算完fif_i后,令contrk+ficontr_k \leftarrow^+ f_i (klk \ge l),其中ll为最小的满足l>il > ialaiEa_l \le a_i - E的下标

同时令Lj=iL_j=ijjcontricontr_i减去自己的contricontr_i

fi+contri f_i \leftarrow^{+} contr_i

时间复杂度O(NlogN)O(N \log N)

吐槽

这题应该是真正意义的防AK题,于是题面理所应当的用了Chao Man,结果Chao Man就被奶死了。 这里是不是应该放一个: alt

谢谢大家。