NOI 2022 众数


1.前言

首先是:关于 /(/rm deque/) ,他死了但没有完全死。

然后是这个大样例说实话有点离谱,最初我在写 /(75/ /rm pts/) 部分分的时候,我动态开点线段树的 /(/rm insert/) ,没有处理好可能会有点被重复使用。我当时没意识到这个问题,就在操作四的时候人为对两个序列做了个启发式合并(不是线段树合并自带的启发式合并),再加上我当时魔改了线段树合并,就莫名其妙的把大样例过了,然后交上去 #11 这个点竟然也过了。离谱,太离谱了!

2.题解

首先我们先解决对正解比较有用的性质 /(C/) 。

对于绝对众数有一个比较简单的做法:摩尔投票。这个东西可以线性的求出一个序列的绝对众数,且支持合并。那么我们对每一个序列维护其摩尔投票的结果,然后询问时把所有序列的结果合并起来即可。

但是摩尔投票只能处理有绝对众数的序列,所以我们在修改元素值,合并序列的时要验证当前摩尔投票结果是否为绝对众数。验证的时候需要知道当前数一共出现了多少次,所以还需要一个权值线段树来维护每个数出现的次数。以上写起来是不难的,值得注意的是摩尔投票的合并,还是有一点小细节的。

我们再来考虑正解。

现在多了一个删除操作,我们发现这对两个东西有影响。一是数列的摩尔投票结果,二是操作四中合并序列的方法。

对于前者,我们在做动态开点线段树的时候充分利用非叶子节点,统计出来序列的众数出现次数,然后再线段树上二分找到众数是什么。

对于后者,我们要求合并是有顺序的,那么我们可以对序列做启发式合并。这里我们需要一个能访问序列开头元素,结尾元素的数据结构,比较好象的应该就是 /(/rm deque/) ,其他的还有 /(/rm list/) 等。

可惜的是,如果你在程序里面开了 /(1e6/) 个 /(/rm deque/) 的话,很遗憾,你会获得 /(0/) 分的好成绩。原因是你会 /(MLE/) ,/(/rm deque/) 会占用大量的内存(即使它是空的) 。 但事实上,/(/rm deque/) 确实可以,因为我们做的是启发式合并,所以只需要开一半的 /(/rm deque/) 即 /(5e5/) 个,这样就可以卡过去了。但是,安全起见,写 /(/rm list/) 一定比写 /(/rm deque/) 优,所以可以认为 /(/rm deque/) 已经死了。

复杂度:/(/mathcal O(C_m/log C_m)/)

代码:Link

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/282967.html

(0)
上一篇 2022年8月30日
下一篇 2022年8月30日

相关推荐

发表回复

登录后才能评论