Sqrt Technology(长期更新)
Yuno loves sqrt technology!
分块
分块是一种优雅的暴力,巧妙地平衡了时间复杂度。
基本思想是对每一块预处理,查询/修改时对散块进行适当的暴力,使得复杂度正确。
时间复杂度取决于块长,一般可以用均值不等式求出理论最优块长。但是理论最优不等同于实际最优,根据实际情况调试。
基础部分
区间加,区间和
对每块维护
区间加:对散块暴力修改
区间和:对散块暴力将
时间复杂度:设总长度为
区间加,区间乘,区间和
对每块维护
区间加:同上。
区间乘:对散块先下放已有的标记(暴力修改一遍),再对需要修改的暴力修,对整块维护
区间和:对散块中的元素用
时间复杂度
区间加,区间查小于 的值的个数
对每块维护
区间加:对散块暴力修改,改完后重新排序(重构),对整块维护
区间查:对散块直接暴力数(记得考虑
时间复杂度
区间加,区间查 的前驱
要维护的东西同上。
区间加同上。
区间查:散块中暴力找小于
时间复杂度
区间开方,区间求和
对每块维护是否全为
区间开方:观察到在进行若干次开方操作后一段区会都变成
区间求和:散块暴力加,整块加
时间复杂度:暴力修改的次数其实很少,对一个数暴力开方不会超过
单点插入,单点询问
块状链表,将原数列串成链表再分块,设块长阈值为
单点插入:直接插入。若某块块长
感觉不太好写,提供另一种想法:
定期重构一下,每插入
单点查询:先跳整块直到在同一块中,再一个一个跳。
时间复杂度
区间赋值,区间查等于 的数的个数
维护每个块是否纯色以及是哪种颜色。
区间赋值:散块暴力下放标记再赋值,整块直接维护标记。
区间查:散块暴力查,纯色块直接查,杂色块直接暴力。
看上去太暴力了,但是经过一通分析后是但我分析不太明白。
可以观察到一次修改最多使首尾两个散块所在的块从纯色变为杂色,于是均摊下来一次还是
区间查最小众数
预处理
于是可以观察到,一段区间的最小众数只可能是整块区间中的众数或者散块中出现的数。
于是再预处理
查询时枚举散块中的每种数,数出其在散块中的出现次数,再进行比较即可。
散块中数的个数是
另一种解法:
求一个区间内
Ynoi大分块
我妻由乃太可爱了!
虽然叫分块,但是后面的题目还是需要莫队的知识啊。
怀疑有生之年能补完吗......
最初分块
望月悲叹的最初分块。
维护序列
-
将区间
中所有的 修改为 。 -
查询区间
中的第 小。
Sol:
第二分块
突刺贯穿的第二分块。
维护序列
-
将区间
中所有大于 的数减去 。 -
查询区间
中 的出现次数。
Sol:
第四分块
拭尽破净的第四分块。
第六分块
深潜循藏的第六分块。
第七分块
????的第七分块。
第十分块
????的第十分块。
第十一分块
沉滞留驻的第十一分块。
第十三分块
????的第十三分块。
第十四分块
点缀光辉的第十四分块。
莫队
对于序列上的区间询问问题,如果从
具体而言,将询问离线并排序,通过暴力移动当前答案区间
小寄巧:写完add
之后,可以从下到上扫描你的add
,然后从上到下在你的del
函数中执行相反的操作。
可以理解成add
和del
的对称性很高,但是别全用这个寄巧,能想明白细节还是尽量想,别寄了。
莫队擅长于解决单点对于点集的贡献,通常贡献形式为点对,于是考虑问题的时候要抽象成点对的形式,利用一下前缀和/差分之类的。
普通莫队
不带修,区间转移都为
排序方式:左端点所在块的编号升序,右端点升序。
还可以优化:奇偶化排序。左端点所在块的编号升序,当左端点所在块的编号为奇数时,右端点升序,反之右端点降序。
设置块长为
时间复杂度
注意移动区间时要先扩大再缩小,以防出现神秘错误。
带修莫队
强行给普通莫队加上一维时间维,就可以修改了。
也要保证时间维上的移动是
时间维上的移动,要考虑是加上修改还是撤销修改,并且要考虑对当前答案的影响。
块长一般取
排序方式:第一关键字:左端点所在块升序;第二关键字:右端点所在块升序;第三关键字:时间升序。
时间复杂度
树上莫队
回滚莫队
如果在莫队的过程中增加/删除两种操作之一不能实现(或复杂度不正确),就考虑回滚莫队。
回滚莫队不实现难做的操作,而是用撤销影响的方式代替。
不删除莫队
具体操作如下:
-
将询问按左端点所在块升序,左端点同一个块内则右端点升序排序。
-
如果询问的左右端点在同一个块内,特判,直接暴力回答。
-
如果处理到了下一个块,那么清空莫队(撤销影响而非删除),并令莫队的左端点移动到新块的右端点加一处,右端点移动到新块的右端点。并且要清空原有的答案。
-
左端点在同一个块内时,右端点是单调不降的,可以直接移动右端点,不必回滚。
-
而左端点是乱序的,每次移动左端点回答询问后都令左端点回滚到起点,并且恢复原来的答案(具体实现时可以不修改原有答案,用
保存原有答案后对 进行修改,回答询问后把 扔了就行)(还是撤销影响而非删除)。
这样就只有撤销和增加的操作,避免了删除。
分析一下时间复杂度(认为
-
暴力部分,一次最多
,总共 。 -
清空莫队操作,一次
,最多有 个块,执行 次,总共 。 -
移动右端点,同一个块内移动右端点最多
,总共 个块,总共 。 -
移动左端点,一次询问最多
,总共 。
综上,时间复杂度
不增加莫队
类比上文:
-
将询问按左端点所在块升序,左端点同一个块内则右端点降序排序.
-
左右端点同一个块内不需要暴力,但是也可以暴力回答。
-
处理到新块就将左端点设为新块的左端点,右端点移动到序列末尾。(这里要求能够在正确的时间复杂度里进行初始化答案)。
-
同一个块内右端点单调不增,直接移动。
-
左端点乱序,移动后进行回滚。
复杂度同上文分析,
莫队二次离线
当增加和删除的转移复杂度都很高时,考虑二次离线。
我们可以将莫队移动的这些端点同样离线下来计算。前后离线两次,故称二次离线。
具体流程如下:
- 先跑一遍莫队,增/删一个点产生的贡献拆成前缀相减的形式(这里要求贡献具有可减性,可以进行差分)。且形式很特殊,下面进行讨论:
记
真是酣畅淋漓的讨论啊。
-
找到
发明一种数据结构,使得可以 或稍劣的复杂度查询点对点集的贡献, 或稍劣修改点集。 -
先预处理,扫一遍求出形如
以及 的贡献,显然用找到的数据结构直接扫一遍是 的。 -
跑一遍莫队,把要求的形如
的 记录下来,挂在前缀 上。注意到这些点 是一段连续区间,储存时直接存区间即可。注意到产生的区间数是 的,空间复杂度从 优化到了 。总点数因为在跑莫队进行 次移动,是 的。 -
最后在扫一遍前缀,对每个前缀处理它产生的贡献。由于一共
个前缀,每个前缀修改一次,这部分 。一共产生了 个询问点,单次查询 ,这部分也是 的。所以总体复杂度 。
找到的数据结构很可能是分块,也可能是暴力加人类智慧。
修改和查询的复杂度可以稍劣,按照以上复杂度分析下来是对的就行。
特别注意:
一些经典问题
区间颜色种数
典,直接上普通莫队,维护每种颜色出现次数,次数从
区间颜色出现次数与排名之积
这是一次比赛题(2024.11.25 T2)的简化题意:
询问一个区间
看到数据范围猜测莫队。然后看到神秘的区间询问更是莫队了。
式子的后面那一坨其实就是区间内这种颜色的出现次数。
首先是上排序不等式,发现逆序乘上去可以最小化(就是大的出现次数和尽量小的
考虑莫队移动端点时会如何变化。发现考虑次数的排名会遇到“次数的出现次数”的这种概念。
但是先别急,考虑莫队增加一个点的变化,设这个点的颜色为
然后考虑莫队减少一个点的变化,同上设,颜色
思考一下要是有一些颜色的出现次数相同怎么办?贡献似乎不能说就是
转移就可以做到
总的还是普通莫队,
根号分治
我们可以设置阈值
看看题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】