久未放晴的天空,依|

TulipeNoire

园龄:1年10个月粉丝:18关注:17

Ynoi 合集(现已更名:数据结构合集)

注:无特殊说明的情况下,mq 等都视为与 n 同阶。


[Ynoi2010] Fusion tree

感觉很具有启发性的题目。首先我们对于每一个点维护其儿子所组成的 01-trie。父亲的操作就单独处理即可。那么我们的目标其实很明确:就是执行一个对字典树内所有元素加 1 的操作。

而这个操作怎么做呢?我们考虑把一个二进制数反插入 01-trie,具体讲,就是从低位到高位插入。这样你手玩一下就可以发现单次操作可以做到 O(logV) 了。

至于为什么会想到倒插?也许是加法的法则使然。反正这个 trick 记住就行了。


updated on 2024.8.31:哎呀,好像找不到没写过题解的 Ynoi 了。只有炒冷饭了。


[Ynoi2019] 魔法少女网站

当初做这个题的时候就是用的序列分块。感觉其实挺好的。

我们考虑逐块处理。实际上我们就是令小于等于 x 的位置为 1,大于的位置为 0,然后对每一个极长 1 段算贡献。那么散块部分就是很简单的,单点修改直接暴力。主要看整块部分。

我们可以知道任何时候整块产生的影响本质上只有 O(B) 种。那么把这些暴力处理出来过后,查询时我们就可以 lower_bound 块内的权值序列找到相应的那一种直接计算。这个的处理用链表就可以了。至此我们得到了一个 O(nnlogn) 的做法了。

发现复杂度瓶颈在于 lower_bound。我们可以根号平衡,对于整个值域的数维护块内小于等于它的数的个数。这个问题是可以做到 O(n)O(1) 的。至此,本问题就得到了 O(nn) 的解法。

实际上这个做法挺平凡的,没有用到什么比较人类智慧的 trick,思路也较为自然。

[Ynoi2009] pmrllcsrms

远古题了,补一个题解。

考虑按 c 分块。单个块内的直接暴力,然后把块看成整体再维护另外一颗线段树。剩下的情况只有可能是两个块间的情况。去掉 corner cases,我们现在考虑如下情况:

第一个块是 1c,第二个块是 c+12c。把两个块叠在一起,那么所选区间左端点必定在右端点右边。

也就是有两个数组 presuf,每一次操作区间修改某个数组的值,或者询问选出 1i<jc 使得 prei+sufj 最大。这是比较易于线段树维护的。然后依然是用一颗大线段树把每两个块之间的贡献穿起来。

大致思路就是这样,但是细节很多,比如散块,长度不足 c 的块,以及被某个块包含的询问区间等等,而且很卡常。时间复杂度 O(nlogn)。评价一下就是敢往这方面想就能会。

[ZJOI2022] 众数

根号分治厉害题。考虑贡献肯定是左右两边的众数出现次数加上中间众数出现次数,贡献算到左右两边的众数上。我们可以考虑去算每一种颜色的贡献的最大值。把出现次数与 n 的关系分成小数(出现次数少)和大数两种。考虑其中两个众数其中有一种来自大数的情况,我们可以直接枚举两种颜色,然后枚举小的颜色的位置集合,不难发现这个东西是一个最大子段和类似的东西。接下来就是两种颜色都是小数。这种情况枚举外侧颜色并且枚举两边各取多少,然后我们需要快速得到中间的众数出现次数。考虑到都是小数,所以出现次数是不超过 n 的。于是我们可以令 fl,i 表示使得 [l,r] 中众数出现次数大于等于 i 的最小 r。这个可以双指针快速预处理。然后求答案的话对于一个颜色和枚举左边的取数个数,我们可以都做一遍双指针来得到答案。至此这个问题就用时空复杂度 O(nn) 的算法解决了。

本文作者:TulipeNoire

本文链接:https://www.cnblogs.com/TulipeNoire/p/18390853/Ynoi

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   TulipeNoire  阅读(51)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起