分块&莫队
分块:
如果我们把每m个元素分为一块,共有n/m块,每次区间加的操作会涉及O(n/m)个整块,以及区间两侧两个不完整的块中至多2m个元素。每次操作的复杂度是O(n/m)+O(m),根据均值不等式,当m取√n时总复杂度最低。(hzwer)
分块:
王室联邦分块:
用于树上莫队
用法待学
莫队:
普通莫队、带修改莫队、树上莫队、回滚莫队(见全网最详细、最深的四类莫队算法讲解)
普通莫队:
先按左指针所在块升序,同一块按右指针升序。
复杂度:设块长m,共n/m块,左指针移动q·m次,右指针移动n·n/m次,m取n/sqrt(q)时,为n·sqrt(q)
莫队:
把块大小blk设成定值不易出错,方便调块大小卡常。
luogu4396 [AHOI2013]作业
莫队+分块:在区间上莫队,在值域上分块。莫队的转移是O(1)。每个询问求答案是用分块,复杂度根号,查询的总复杂度为q根号n。总复杂度是O(n·sqrt(q)+q·sqrt(n))
luogu1903 [国家集训队]数颜色/维护队列
带修改莫队:多了一个时间轴。排序第一关键字是左端点所在块编号,第二关键字是右端点所在块编号,第三关键字是时间。左指针移动的复杂度为q·n,右指针的复杂度为n/m·n,时间轴的指针的复杂度为n/m·n/m·q,n和q同阶的时候,m取n^(2/3)时最优。比较需要调块大小。
atcoder1219 歴史の研究
回滚莫队:用来处理不适合添加或者删除的情况。对于处于同一块的左指针,每次移动之前将左指针放在下一个块的第一个位置,移动之后再把左指针放到下一个块的第一个位置。这样可以使得问题只有添加没有删除(或者删除变的可以处理)。复杂度同普通莫队。
区间众数
离线:回滚莫队 时间n·sqrt(q) 空间n
在线:分块 时间n·sqrt(q) 空间n
luogu5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III
区间众数 众数的次数 在线
先离散化数据,将每个数据都放到对应的桶里(vector),并记下排名。
再预处理一个f[i][j]表示第i个块到第j个块中的众数是多少,同时也可以记下众数是什么。
对于每一个[l,r],ans开始是f[bl[l]+1][bl[r]-1]为中间块的众数。
对于左边的数字,在其对应的vector中找从他开始往后ans个数的位置是否<=r(首先要保证有后ans个数),如果有则++ans
对于右边的数字,在其对应的vector中找从他开始往前ans个数的位置是否>=l(首先要保证有前ans个数),如果有则++ans
复杂度:ans自增最多blk次,因为每次更新的数的位置要跨越[bl[l]+1][bl[r]-1],这样就是两边区间的数的个数。预处理复杂度为n·n/m,每次查询复杂度为m,总复杂度n·n/m+q·m