整体二分
——爆改cdq。
整体二分可以在 的时间复杂度内离线、批量处理区间第 排名问题。如果一个一个二分答案处理询问,那每次询问都要遍历整个区间 遍,复杂度将达到 ,是我们不能接受的。
注意到每次二分 check()
都会遍历整个数组(区间),但只进行了一次查询,效率低下。我们希望可以将有需要的询问放在一起查询,并且只修改数组中有用的位置。因此,我们可以把数组的每个位置看成一个单点修改操作,和查询操作混合之后送入 cdq 分治中“整体”地进行二分。
大体思路和 cdq 相同:
- 每次递归传入操作集合
op
和区间 ,表示修改操作的val
和查询操作的答案都位于值域 内; (开始时序列默认为空,每一个初始数字视为一个修改) - 统计值域左半区间内的修改对所有查询的贡献; (将所有 的修改按时间顺序加入树状数组,查询操作即在树状数组上做区间查询)
- 判断查询应下放到左右哪个区间; (如果区间查询的结果 满足 ,说明第 小的数字一定小于等于 ,否则一定大于 )
- 分割操作至左右两区间,递归调用;
(注意,如果判断查询的答案在值域右半区间,则应把左半区间的贡献计入,执行
k -= cnt
)
核心:
- 通过 cdq 压掉值域维度,使树状数组可以用来维护数组下标;
易错点
把查询下方到右区间时,要把左区间的贡献减去。
剪枝优化
因为整体二分是值域上的递归,若不剪枝,时间复杂度会达到 。所以要判断操作集合是否为空,若为空则直接返回即可。这样能保证每个操作都只会产生一条 的路径,从而将递归时间复杂度限制在 。
P3834 【模板】可持久化线段树 2
求给定序列的区间第 小。
代码
P2617 Dynamic Rankings
代码
P3332 [ZJOI2013] K大数查询
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
|
P1527 [国家集训队] 矩阵乘法
代码
P7424 [THUPC2017] 天天爱射击
代码
P3527 [POI2011] MET-Meteors
首先破环为链:
- 对于操作区间(指陨石落下的区间)满足 的情况,此时 就是修改区间,无需额外处理;
- 对于操作区间 的情况,将其拆为 即可;
这样问题就转化到了链上。
我们视每次陨石为一次(区间)修改操作,每个国家的 为(查询第 小)一个查询操作,进行整体二分。可以这么理解:将每次陨石拆成单块的陨石(比如一次降落三块,就拆成 );然后每个国家就是在查询落到本国家的时间第 小的陨石是第几次降落下来的。
但是一个国家的空间站是分散的,不是一个连续的区间,如何统计?
但是我们注意到每一个位置只会有一个国家的空间站,也就是说,所有国家的空间站的总数为 。对于每一个查询,我们可以枚举这个国家的所有空间站。这样即使我们枚举了所有国家,均摊时间复杂度也不会超过 。
因此,在二分时:
- 对于修改操作:使用树状数组区间处理所有 (降落时间小于 )的修改操作;
- 对于查询操作:暴力枚举该国家的所有空间站,单点查询每一个空间站在本次递归中收获了多少陨石,直接进行累加,和 比较,决定将查询操作下方到左区间还是右区间。
时间复杂度分析
对于每个修改操作(陨石下落),会产生从根到叶子的一条路径,长为 ;在每个节点(二分的一个区间)处会进行两次树状数组的操作,时间复杂度 ;因此修改操作产生的总时间复杂度为 ;
对于每个查询操作,在每个节点处会产生 的时间复杂度( 表示每个国家分到的平均空间站数量),因此总的均摊时间复杂度为 ;
综上,代码的总时间复杂度为 ,可以通过本题。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
|
P3242 [HNOI2015] 接水果
整体二分套扫描线。
题目要求查询 被路径* 包含的路径中,权值第 小的权值,考虑整体二分。
*注:本文中提到的所有路径 ,默认满足 ;若题目输入不满足此条件,执行
swap(x, y)
即可。
查询第 小,考虑整体二分。经过 cdq 之后,我们需要解决一个子问题:实现以下两种操作:
- 向集合中加入一条路径;
- 给定路径 ,统计集合中被路径 包含的路径数量;
我们发现,路径 包含路径 ,本质上是对两端节点 和 做了 dfn
序的约束。 和 的 dfn
序的约束相互独立,这是一种二维数点问题,考虑使用扫描线求解。
当 和 满足 时(返祖链),记 表示 向 方向的直系儿子。
具体的,对于一个修改(盘子) ,会对所有 包含它 的查询产生 的贡献:
- 当 时,会贡献到满足以下条件的查询:
或
- 当 时( 不会等于 ,因为 的
dfn
序比 小),会贡献到满足以下条件的查询:
这种约束可以直接使用扫描线统计贡献。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
|