关于二次分块这么一个奇奇怪怪的东西

自己口胡了一个数据结构题:

维护排列 \(s\),支持如下操作:

  1. 查询 \(s_l,s_{l+1},\cdots,s_r\) 内大于等于 \(a\) 且小于等于 \(b\) 的第 \(k\) 小数;
  2. 交换 \(s_x\) 和 \(s_y\) 的值。

然后口胡了一下做法。

首先考虑没有修改操作的情况。考虑对值域分块,块长为 \(\sqrt n\)。维护 \(sum_{i,j}\) 表示 \(s_1\) 到 \(s_j\) 有多少个数落在第 \(i\) 块中。

那么显然预处理部分是可以 \(O(n\sqrt n)\) 搞的。

然后考虑查询。从 \(a\) 所在的块到 \(b\) 所在的块扫描一遍,每次通过 \(sum\) 求出 \(s_l\) 到 \(s_r\) 内有多少个数落在此块内,并累加到计数器 \(cnt\) 中。一旦 \(cnt\ge k\),就说明答案在当前块中,直接退出,然后再扫描一遍当前块,就把答案搞出来了。

接下来考虑修改操作。考虑将一个操作拆解为在位置 \(x\) 上删除 \(s_x\),添加 \(s_y\),在位置 \(y\) 上删除 \(s_y\),添加 \(s_x\) 这四个小操作。对于第一个小操作,设 \(s_x\) 所在的块为 \(p\),那么需要将 \(sum_{p,x},sum_{p,x+1},\cdots,sum_{p,n}\) 全部减 \(1\)。剩下的三个同理。这个东西需要在 \(O(\sqrt n)\) 的时间以内解决,否则无法保证复杂度。

而进行查询操作时,将要 \(O(\sqrt n)\) 次使用 \(sum\) 的值。因此每次获取 \(sum\) 的时间只能为 \(O(1)\)。

考虑再用一个数据结构来维护 \(sum\) 数组。这个数据结构需要满足如下条件:

  • \(O(\sqrt n)\) 以内的区间加

  • \(O(1)\) 的单点查询

那么已经呼之欲出了:序列分块。

综上所述,可以在用 \(sum\) 数组维护值域分块以支持查询操作的同时,用序列分块来维护 \(sum\) 以支持修改操作。

这样就做到了总的 \(O(n\sqrt n)\) 的时间复杂度。

空间复杂度也为 \(O(n\sqrt n)\)。

在网上查了一下并没有发现类似的东西。于是我给这个东西取名叫做二次分块。

上一篇:[学习笔记]无向图三元环计数


下一篇:洛谷 P5071 - [Ynoi2015] 此时此刻的光辉(莫队)