Fedya the Potter Strikes Back
非常有启发性的题目。 首先考虑一下这个静态的怎么做。 就子串匹配这个东西,第一反应是 SA 或者是 Z 函数。 相当于是固定左端点,然后右端点就是一个区间,这非常适合于这类什么区间最小值求和之类的,因为你只要单调栈维护即可。 但是他们是不好在线做的。 然后我们考虑转一下思路,考虑 kmp,kmp 是可以在线的。 乍一看这个 kmp 固定右端点左端点不连续。但他有一个好处是他均摊是对的。 然后我们一个很暴力的想法就是每次前缀直接把他的所有的 border 全都枚举一遍。 这显然糖丸了。 但一个启发是,我们可以实时维护 border。因为一个左端点出来就不会再进去了,然后我们就可以直接维护。 具体来讲我们相当于是搞一个 border 的左端点的 set。然后每次只能要么把不对的一个一个踢掉,然后再把当前的点加进去。 于是问题变成了我们如何快速找到那些不对的。 你注意到一个事情,就是他这个所有的 border 关系形成了一棵树,然后我们每次相当于取一个到根的链。 然后我们每次直接给每个节点维护一个他下一个的字符是他的颜色。 然后我们就相当于要把这个链上所有颜色不对的全干掉。 这是好做的,有各种做法比如倍增。但最好的做法就是你直接记录每个点最靠下的不同色的祖先。然后暴力跳均摊 $O(1)$。 这个东西应该是相当有用的,因为你考虑你严格拓展了 kmp。你不仅知道了这个 border 树是怎么样的,你甚至可以直接实时维护这个 border 是啥。 然后我们具体如何统计最小值之和? 我们都维护了,我们直接给每个 border 维护他们的最小值就可以了。 我们相当于要进行这些操作:加上一个数,全局对 $w$ 取 min,删掉一个数。 他给出了一个相当有趣的做法,你考虑用 map 维护 cnt。 加上一个数直接加。 取 min 就直接暴力把 $>w$ 的全部 erase 了然后加到 $cnt_w$ 上。 删掉一个树直接删。 因为每次 map 不同元素数都只会加减 $1$ 因此均摊是对的。