CF840D 题解
FstAutoMaton · · 题解
题解里面都是随机化,根号分治,主席树之类的。菜鸡表示完全想不到啊!!于是今天在外面游荡的时候胡了一个简单易懂的做法。
前情提要:本题解所用方法几乎是算法堆叠,毫无思维含量,所以不建议想练思维的巨佬们观看。
首先看到区间数字出现次数首先想到莫队。
那么我们很容易可以想到一个做法:用莫队维护数字出现次数,然后对于每个询问,从小到大枚举答案会是那个数,然后找到最小的满足条件的数。
然而这样做是
不难想到,我们可以二分这个最小的数。
假设当前二分到了
用权值线段树或权值树状数组可以做到
这个做法有一个很重要的点(正解也需要这一点):用线段树维护显然直接做就可以了,但是树状数组貌似不太能。
因为我们要求出的是前缀最大值,而莫队删除元素时可能会让最大值变小,这一点极其不好维护。
所以我们要避免删除元素。
那么莫队就要变为回滚莫队。(不会回滚莫队可以看这不要脸的宣传)
然而
不难发现,我们对元素进行修改会进行
所以我们需要一种修改复杂度极快,查询复杂度中等的数据结构来维护这些信息。
值域分块 可以很好的解决这个问题。
和树状数组一样,值域分块也不能像线段树一样快速合并信息所以我们也需要回滚莫队。
那么现在我们每次修改是
而我们需要查询
假设我们要寻找的答案为
那么第 这不废话。所以我们可以从小往大暴力枚举块,然后找到最靠前的那个最大值大于
这样就可以在
知道了答案在的块后,答案就出来了。
因为每个块的长度只有
这样我们就把寻找答案的复杂度做到了
代码其实很好写,思路很顺,所以大概半个小时左右就能写完。
然后回滚莫队的常数貌似不是一般的大(也有可能是我写丑了),所以卡了很久的常。
正常代码(过不了,没卡常)
AC代码