序
感谢@hzwer大佬出的练习题
题目链接LOJ
本蒟过弱,实在不知道怎么压缩代码量了->_->
数列分块入门 1
给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及区间加法,单点查值。
将$n$个数,按照每$\sqrt{n}$为一个块标记.
1 | belong[x]:元素x所在的块的编号,样例代码中为bl[x]; |
每次对所给的$[l,r]$区间进行讨论,分为”单蹦”和”块”,对于不满块的数,直接暴力修改.
对于满足块的数,直接打一个标记,当访问的时候再进行修改即可,类似于线段树$lazy$.
1 | /* |
数列分块入门 2
给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及区间加法,询问区间内小于某个值 $x$ 的元素个数。
区间加法仿照$1$即可.
对于每一个块内的数据,为了方便查询,我们分便对每一个块内的数据进行排序.
对于不满足块的数据,我们暴力处理,再将这个块内的数据排序,
满足块的区间,我们依然是打标记即可.
查询的时候,二分查找即可.
1 | const int MAXN = 1e5 + 10; |
数列分块入门 3
给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及区间加法,询问区间内小于某个值 $x$ 的前驱(比其小的最大元素)。
和$2$类似.
出题人的想法:
可以在块内维护其它结构使其更具有拓展性,比如放一个 set ,这样如果还有插入、删除元素的操作,会更加的方便。
1 | const int MAXN = 1e5 + 10; |
数列分块入门 4
给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及区间加法,区间求和。
求和预处理一下就阔以了,打标记的时候是长度$*$加法
1 |
|
数列分块入门 5
给出一个长为 $n$ 的数列 ,以及 $n$ 个操作,操作涉及区间开方,区间求和。
这个题目其实比较搞人==
对于一个数,其属于${-2^{31},2^{31}-1}$,最多开方不超过$4$次.
还是和之前一样,单个暴力,整块标记.
对于一个块,如果开方次数超过$4$次,或者整个块只有$1$或$0$,我们就可以认为不需要对其处理了,只记下和即可.
自己代码实现的时候,注意细节.
1 | typedef long long ll; |
数列分块入门 6
给出一个长为 $n$ 的数列,以及 $n$ 个操作,操作涉及单点插入,单点询问,数据随机生成.
到了喜闻乐见的动态分块了$23333$.
$c++$的$vector$大法好,我是不会用指针写链表的,拒绝
每次插入一个数,就找到对应的块,扔进去就行.
将插入的次数记下来,当次数超过$\sqrt n$的时候就进行重构,也就是重新分块.
然后就没有然后了.
1 | const int MAXN = 1e6 + 10; |
未完待续