P4143 采集矿石 题解

发布时间 2023-12-02 19:32:35作者: 蒟蒻·廖子阳

题目传送门

  • 给出字符串 \(s\),以及数组 \(a_1\sim a_{|s|}\)

  • 定义一个子串的排名为:字典序比它大的本质不同的子串个数 \(+1\)

  • 定义一个子串 \(s[l,r]\) 的权值为 \(\sum\limits_{i=l}^ra_i\)

  • 求有多少个子串的排名等于权值。

  • \(|s|\le 10^5,0\le a_i\le 1000\)

首先对 \(s\) 进行后缀排序,然后考虑每一个左端点 \(l\),不难发现随着右端点 \(r\) 的增大,子串的排名单调递减,权值单调不降。

所以可以二分出满足条件的最小 / 大右端点。

考虑如何求出一个子串 \(t\) 的排名。可以用本质不同子串数减去比它小的。

前半部分运用经典结论即为 \(\sum\limits_{i=1}^n (|s|-sa_i+1-\text{height}_i)\),我们考虑如何求比它小的本质不同子串数。

可以二分出以这个子串为前缀的后缀排名区间 \([L,R]\)答案即为排名为 \(\boldsymbol{[1,L)}\) 的后缀带来的本质不同子串个数。

  • 充分性:

    若一个子串 \(str\) 在排名为 \([1,L)\) 的后缀中作为前缀出现,那么这个后缀 \(s[i,|s|]\)\(s[l,|s|]\)\(\text{LCP}\) 长度一定小于 \(\boldsymbol{|t|}\)。即两个后缀可以在第 \(|t|\) 个位置之前可以找到不相同的位置。而由于 \(s[i,|s|]\) 这个后缀排名更小,在这个位置一定 \(s[i,|s|]\) 这个后缀小于 \(s[l,|s|]\)

    考虑 \(str\) 是否跨过这个位置,若不是,则在前 \(|str|\) 位两串相同,第 \(|str|+1\)\(str\) 为空,字典序极小。

    若跨过,则 \(str\) 在这个位置小于 \(t\)

  • 必要性:

    考虑这两个子串第一次不同是在某个位置,这个位置一定在两个后缀中。

正确性证好了。这个东西也是考虑每个后缀带来的本质不同子串。即可以这么求:

\[\sum\limits_{i=1}^{L-1}(|s|-sa_i+1-\text{height}_i) \]

于是做完了。时间复杂度为 \(\mathcal{O}(|s|\log^2|s|)\),空间复杂度为 \(\mathcal{O}(|s|)\)

提交记录 代码