快乐的一天从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]\)内这个数出现了几次。
完结撒花。