题解[Ynoi2006]rsrams
StaroForgin · · 题解
非常有幸在某谷上成为了跑得最快的一个至少在笔者写题解时是如此的,所以来水一篇题解。
顺便批判一下某个为了让题目价值最大化的人,居然把公开了的题隐藏了又拿出来卖(详见某谷评论区),笔者不幸成为了受害者。(;´д`)ゞ
好的,那让我们开始讲讲这道题吧。
首先让我们想想颜色数量比较少,譬如颜色数为
由于它要求的是区间段内一种颜色的出现次数严格大于其它颜色的数量,我们不妨将该种颜色的值看作
那许多颜色时,如果我们再一个颜色一个颜色的这么做不就 这不 T 飞。
没事,我们观察到对于每个颜色真正有用的区间是非常少的,经常会出现很长一段区间一个该颜色的点都没有的情况。
我们可以对于该颜色可能成为绝对众数(也就是它的出现次数超过一半),找到它的可能区间,只考虑这个区间内众数的计算。对于这个可能的区间,我们可以去找它的最左左端点与最右右端点,把它们之间看作这种颜色的一个可能区间。
下面给出一种比较简单的找法,从左到右枚举每个该颜色的位置,选中它左边第一个尚未被选择到的不是该颜色的位置。再从右到左枚举每个该颜色的位置,选择它右边第一个尚未被选择的不是该颜色的位置。
显然,所有选择位置与该颜色的位置构成的连通块就是一个可能的区间。你再选连通块外的任意一个点,必然不可能构成包含该连通块中点的总和为正的区间,也就不会对答案产生任何贡献。
好的,这样我们就能非常简单地求出我们的可能区间了。可以发现,这个可能区间有一些非常好的性质:
-
总长度是
O\left(n\right) 级别的。显然,每个位置最多只会让两个与其同色的点被选择,总长度不会超过3n 。 -
每一个位置最多被
O\left(\log n\right) 个不同色的可能区间覆盖。由于我们是每种颜色计算可能区间时是计算的一个连通块,所以每种颜色的可能区间时不想交的,覆盖每个位置的可能区间最多只有一个。先假设该位置时可能区间的某个端点,将所有可能区间按长度排序,下一个区间的颜色要成为绝对众数,它包含的该值颜色必然会超过其它颜色,可以发现,这样它是在不断翻倍的,是
O\left( \log n\right) 级别。即使该位置不是可能区间的端点,也最多会扩大常数倍,该结论仍成立。
首先,只有当询问区间与可能区间相交时,可能区间才会对答案产生贡献。考虑询问区间与可能区间相交的三种情况。
- 我们的询问区间包含了我们的可能区间。
- 我们的询问区间被我们的可能区间包含。
- 两者不存在包含关系。
其中,对于第一种情况,显然就是个二维数点问题。我们可以先将每个可能区间的总贡献值算出来,然后加在点上。排序后用一个树状数组就可以
对于第二种情况,我们可以询问区间肯定包含可能区间的某个前后缀,我们不妨考虑把这个前后缀的答案预处理出来,再在询问区间的左右端点上,枚举处于这种情况的可能区间有哪些,将前后缀的贡献加入答案,显然,这部分时间复杂度是
诶,单纯预处理一个全局或者前后缀的逆序对数量是
可以发现,我们值的变化都是形如
我们可以考虑记录
假设我们现在右端点处值为
这样,我们就可以做到
我们现在再来考虑我们的第三种情况,显然,这就相当于查询我们的询问区间在全局区间中对应的区间逆序对数量,这不是可以考虑莫队吗?
我们可以将所有的这样的询问离线下来,对于每个可能区间单独做莫队,依旧用我们上面的方法实时维护答案,也就没必要二次离线了。
每个长度为
最后只需要把每一类对该询问区间的贡献加在一起,就可以得到该询问区间的总答案了。
总时间复杂度为
code