CF765F Souvenirs 题解
简要题意:
给定一个序列,每次查询一个区间差最小的2个数的差。
解法1(我个人最喜欢的解法):
考虑莫队。
当一个不太经典的数据结构出现时,如果能离线,那么莫队是最自然的想法。
这个问题具有一个很显然的性质就是,对一个区间排好序后,答案一定是某相邻的两个数带来的,所以我们的莫队大概率离不开维护顺序这个问题。
如果能把顺序很快速的维护出来,我们的答案只需要同步于维护顺序的时候维护即可。
显然的,固定住区间某一段,答案关于区间长度是有单调性的。这提醒我们使用只加入莫队(回滚莫队),每次加入右端后,临时加入左侧短区间,然后更新答案,再撤销左侧短区间。
此时我们就已经做到了 $O(n\sqrt q\log n)$ 的复杂度,但是这显然太卡常了,过不去,考虑优化。
刚刚我们的 log 是因为,我们维护顺序使用了平衡树,这里可以考虑压位trie科技,把log强行压成亚log。
但是仔细回想所学,只删除莫队,是通过链表的方式维护的顺序,而且可以做到 $O(1) $ 的维护顺序,我们刚刚不使用他是因为他是删除,而删除是没法维护答案的。
——“为何不把两者结合呢!”
考虑一个这样的算法:你通过先构造链表,然后清空它,最后再撤销刚刚的行为,做到 O(1) 加入维护顺序。
——“用删除的撤销来实现插入!天才的想法!”
至此核心思想已经初具雏形,具体实现留给读者思考。
参考题解:https://www.luogu.com.cn/blog/namelessgugugu/solution-cf765f (里面讲了莫队的详细实现,O(nsqrt(n)))
解法2:
考虑分块。
和莫队一样,读者认真思考就会发现,分块和莫队面临这同样的问题:O(nsqrt(n)logn) -> O(nsqrt(n)) ?
直接粘题解:https://www.luogu.com.cn/blog/Mrsrz/solution-cf765f
浅析核心思想,这里利用归并,去掉了一个 log ,与我们刚刚莫队的做法结合起来思考,我们其实可以发现,预先有序的数组维护顺序,似乎是容易去log的
解法3:
极其优秀且富有技巧性的标算。O(nlognlogV),非常优秀。
直接粘题解: https://www.luogu.com.cn/blog/lhm126/solution-cf765f
再附上一个不同于主席树的神奇的实现:https://codeforces.com/contest/765/submission/40982512
(注:把归并排序的过程数组存储下来,每个节点是对应区间的数组,类似划分树)