今天无意中碰到这么一道题:
作为一个 WOT 玩家感觉题面十分亲切
值得一提的是我还真和 lxl 语音联机打过 WOT
题目就是裸的 RMQ 问题
然而数据非常大,普通的 O(nlog2n)−O(1)rmq 肯定是无法通过得了的
笛卡尔树欧拉序 ±rmq 的 O(n)−O(1)太复杂了
(而且空间上可能有点过不去?)
lxl 提供了一种分块思想的 rmq,可以让预处理复杂度做到 O(n),单次询问复杂度一般为 O(1),最坏为 O(log2n)
做法就是把序列分块,块大小为 log2n,在块与块之间用普通 rmq 维护块间最大值,块间 rmq 预处理复杂度为 O(nlog2nlog2nlog2n)<O(n)
然后每个块再维护一下块内前缀最大和后缀最大
询问的时候对于询问区间中间的整块用块间 rmq 询问最大值,边上的不足一整块的用前缀/后缀最大询问一下,询问一次是 O(1)的
这样看起来很棒棒,然而有个非常奇妙的问题——如果询问的两端点在同一个块内就 GG 了
如果在同一个块内就只好暴力算答案,由于块大小为 log2n,所以这样询问复杂度最坏是 O(log2n)的
但是一般出题人不会卡这个算法,卡也不太好卡,你可以微调分块大小让出题人无从下手
而且这题数据又是随机的,因此可以随便做啦!
我分块习惯分成 2k这样的大小,因为编译器会对 2k这样的数字的取模和除法做优化,会快一些
但这题还是有点卡常,我把块大小开到 64才过
代码:
2 条评论
foreverpiano · 2019年3月29日 6:40 下午
lxl?
Remmina · 2019年3月29日 9:22 下午
已修正,很抱歉 QAQ
(主要是 Code+群里天天刷 llx 就口误写错了)