• [复习]分块/莫队


    首先广为人知的莫队复杂度证明:网上题解证明的大部分有bug,这里改进一下
    总询问为\(q\), 总大小为\(n\)
    莫队复杂度证明:设块长为\(S\),则共有\(B := n/S\)个块
    首先考虑块内移动:
    单个块考虑
    右指针:单调递增,\(O(n)\)
    左指针:每个询问最多移动块长,设第\(i\)块询问个数为\(f(i)\)\(S\) , \(f(i)*S\)
    总复杂度:
    \(B*n\)
    \(\sum_{i = 1}^{B}{f(i)*S}\) = \(S*\sum_{i=1}^{B}{f(i)}\) = \(S*q\)
    \(n/S*n+S*q\) = \(n^2/S+S*q\)
    然后考虑块间移动:
    左:\(2*S\)
    右:\(O(n)\)
    总复杂度 \(O(B*(S+n))\) = \(O(n^2/S+n)\)
    算法总复杂度
    \(O(n+2*n^2/S+S*q)\) = \(O(n^2/S+S*q)\)
    对勾函数,当\(S = \sqrt{n^2/m}\) = \(\frac{n}{\sqrt{m}}\)时候,总复杂度为\(O(n\sqrt{m})\)
    接下来是待修改莫队
    设块长为\(S\),共有\(B := n/S\)个块
    分开考虑每个指针的移动
    时间指针:每个右端点块会最多移动\(q\)次,每个左端点块有B个右端点块,所以共有\(B^2\)个右端点块了,\(O({(\frac{n}{s})}^2*q)\)
    左右指针与刚才的分析一致
    所以是\(O(S*q+\frac{n^2}{S}+{(\frac{n}{S})}^2*q)\)

    根据ouuan dalao的博客, S取值为这个时函数有最小值
    然后当\(q\)\(n\)同阶时候小值,为\(O(n^{\frac{5}{3}})\)
    注意点:
    1.求块长时候让\(S = ceil(n/sqrt(m))\)
    2.求bel数组时候\(bel[i] = ceil(1.0*i/S)\)
    3.分块求L数组与R数组时候 要把最后一个块的R赋值成n
    4.注意运算顺序,不要用\(a[++i] = node(i,a,b)\)这样的操作,可能先算++i再调用构造函数,也可能先用构造函数再用++i, 所以用逗号表达式一劳永逸++i, a[i] = node(i, a, b)即可
    5.注意原始信息和维护信息的区别,比如sort块内的时候不要干扰原始信息

    莫队常用技巧:
    奇偶性排序:
    排序函数里面这么写

    if(pos[a.l] != pos[b.l]) pos[a.l]<pos[b.l]
    else return pos[a.l]&1?a.r<b.r:a.r>b.r;
    

    大概就是减少右端点移动
    回滚莫队:
    给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问。每次询问某个区间[l,r]中,最长的值域 连续段长度。
    从上到下一次
    做法一:权值线段树+普通莫队,但是复杂度过大,是\(O(logn*n\sqrt(n))\)
    做法二(我的做法):权值并查集,求把连续段整成siz,复杂度\(O(\sqrt{n}log(n)q+n\sqrt{n})\)
    做法三:题解做法,求出值域上向左向右延伸的最大长度
    参考资料:
    \(\large\boxed{\textsf{ouuun的博客}}\)

  • 相关阅读:
    二维数组中的查找--python实现
    redis 学习笔记二
    redis 学习笔记(一)
    mysql sql知识总结
    工作或日常生活工具网站
    Git冲突:commit your changes or stash them before you can merge. 解决办法
    pandas 学习二
    python supervisor 守护进程 防止进程掉线
    pandas 学习
    django 定时器
  • 原文地址:https://www.cnblogs.com/cdsidi/p/15868671.html
Copyright © 2020-2023  润新知