快乐的一天从AC开始 | 20210709 | P4168

题目链接

早上补昨天的题,被莫名其妙的问题关了,然后就去上班了。

白天自闭看代码看了一天,晚上下班又被这题关了,更加自闭了。

入职一周,啥东西都不会,一行代码没写,学技术还越学不会的东西越多。之前但凡多用点心学技术现在也不至于这样。

带薪自习总觉得内心不安,很怕试用期没过人就没了

明天不上班(

心路历程

题目翻译一下就是区间众数。

众数不满足可减性,主席树被关了。

然后想到莫队,回滚莫队确实可以搞区间众数。但是很不幸,本题强制在线,莫队也被关了。

然后一看数据范围,直接莽分块吧。(暴力美学

思路

首先\(a_i \le 10^9\)太大了,离散化一波,现在\(a_i \le n\)

对于询问\([l, r]\),如果其属于一个块,那么直接暴力扫一遍就好了。

否则,它就可以至多分成3段,两边的两块不完整的块,以及中间一段完整的块。通过观察可以得到:最终的答案,要么是中间的众数,要么是两边上的数。想象成原本只有中间的一段,然后向两边扩展,只有再两边出现才有可能更新众数。两边上的数只有\(O(\sqrt{n})\)个,这个性质就很nice了。

现在,可以\(O(n \sqrt{n})\)预处理出第\(i\)块到第\(j\)块的众数\(z_{i, j}\)。枚举起点,每次令终点加一,再枚举新增这一个块中的数,看能不能更新众数。这样答案的初始值就可以\(O(1)\)得到了。

然后就是枚举两边的数,看\([l, r]\)内这个数出现了多少次,判断能不能更新答案。

  • 可以\(O(n \sqrt{n})\)暴力预处理前\(i\)块中\(j\)出现的次数\(p_{i, j}\)。现在可以\(o(1)\)得到中间那一段中某个数出现了多少次。对于每个询问,先遍历一遍两边的数,搞个map存出现的数及其次数。然后遍历map,判断一下就完事了。
  • 口胡:搞\(n\)vector保存每个数出现的位置,然后每次询问,遍历两边的数,然后两次二分可以确定\([l, r]\)内这个数出现了几次。

完结撒花。

posted @ 2021-07-09 23:52  _Backl1ght  阅读(31)  评论(0编辑  收藏  举报