分块——从入门到放弃

前言

博主因为是蒟蒻,所以很多时候想不出线段树标记下传,所以就写分块暴力下传。为了造福人类,就准备分享一下写分块的经验。

温馨提示

本文不赘述基本写法,只讲述思路。

基础分块

例题 1

题目传送门

先化简题目意思:

维护一个序列,维护区间加和区间大于 \(x\) 的数的数量。

首先分块后问题拆成了块内大于 \(x\) 的数的数量之和与散块大于 \(x\) 的数的数量之和,散块直接暴力查询就可以了。

块内查询怎么搞?我们知道,假设数据有序可以直接二分。

我们又注意到,块内加不影响数据有序性。

所以答案就呼之欲出了。

块内二分,散块排序重构。

例题 2

题目传送门

考虑分块。

显然需要维护开着的灯的数量。

散块可以暴力搞。

整块打标记可以将开着的灯的数量变成块长减去开着的灯的数量。

那么就做完了。

维护置换

例题 1

题目传送门

考虑到 \(\operatorname{popcount}(x)\) 操作后块内不同的数的数量不超过 \(\log V\)

因此块内维护一个长度为 \(\log V\) 的置换,散块操作再重构即可。

值域分块

例题 1

题目传送门

这种鬼畜的问题优先考虑莫队。

现在的问题就只剩下一个,维护集合 mex

考虑维护一个桶。

那么如果我们可以桶分块,并维护每一块中一共出现了多少种数字,这个显然很容易 \(O(1)\) 维护。

那么在查询的时候,对于某个块如果所有数字都出现过就跳过,否则的话由于 mex 一定在其中,那么就暴力查找即可,复杂度是 \(O(\sqrt n)\) 的。

注意到莫队只在移动过程中对桶修改,而在回答询问时才在桶中查询。

所以总复杂度仍然是 \(O(n \sqrt n)\) 的。

值域并查集

例题 1

题目传送门

首先我们发现在修改操作之后不同数的数量一定不增。

这是一个提示。

那么考虑:令块内最大值为 \(k\)\(k \leq 2 \times x\) 则将大于 \(x\) 的数减去 \(x\),也就是花费 \(k - x\) 的势能让 \(k\) 减去 \(k - x\),否则先打一个减 \(x\) 的标记,再让小于 \(x\) 的数加上 \(x\),即花费 \(x\) 的势能让 \(k\) 减少 \(x\)

然后考虑怎么维护这个东西,显然可以用一个并查集维护每一个值变成了什么,那么就可以做到 \(O(n \sqrt n)\) 时间的维护了然而空间依然过不去,但是卡空间的技巧之后再说

posted @ 2024-01-31 00:01  ChiFAN鸭  阅读(19)  评论(0编辑  收藏  举报