问题
给定序列ai和常数E,问有多少种将其划分为若干非空段的方案,使得相邻两段的最小值至少相差E。
题解
设fi表示,已经考虑a1…ai的划分,且ai为其所在段的首个最小值,有多少合法划分方案(ai所在段可能还未闭合)。
考虑对于i,哪些区间[l,r]满足ai是首个最小值
用单调栈预处理i左侧第一个≤ai的位置Li,以及i右侧第一个<ai的位置Ri
则Li<l≤r<Ri满足ai为其首个最小值
考虑哪些j (j<i) 可以用fj贡献fi
第一类
aj≤ai−E
考虑j和i之间有多少种可能的断点
依据我们对i成为最小值的区间的观察,断点必须在Li右边
又注意到这些j显然满足j≤Li
故(Li,i]都可成为j所在段与i所在段的断点
对于一个j,它在i∈(j,Rj)可能成为一个能对i做贡献的j
使用树状数组,维护对于目前i可贡献的那些j,以aj为下标的f的前缀和
fi←+(i−Li)∗bit.query(ai−E)
第二类
aj≥ai+E
考虑j和i之间有多少种可能的断点
依据我们对j成为最小值的区间的观察,断点必须在Rj左边
又注意到i≥Rj
故(j,Rj]都可以成为j所在段和i所在段的断点
ai必须是断点到i这一段的最小值
则fi从第二类j获得的实际贡献contri,应为满足要求1.的所有j对其的贡献之和∑jfj×(Rj−j),减去contrLi
如此一来便能抵消所有ai并非断点到i这一段的最小值的情况下的非法贡献。
计算完fi后,令contrk←+fi (k≥l),其中l为最小的满足l>i且al≤ai−E的下标
同时令Lj=i的j的contri减去自己的contri
fi←+contri
时间复杂度O(NlogN)
吐槽
这题应该是真正意义的防AK题,于是题面理所应当的用了Chao Man,结果Chao Man就被奶死了。
这里是不是应该放一个:

谢谢大家。