zoukankan      html  css  js  c++  java
  • ZROI 19.08.03 分治与离线

    • 经典问题,给一张图,支持加边/删边/询问两点连通性。

    离线统计边权(删除时间),lct维护最大生成树即可。

    也可以按时间分治,维护一个可回退并查集即可。


    • 主定理

    很好用,但是记不住。

    有一种简明的替代方式:画一棵递归树,考虑层数和每层的节点数(线段树分析.jpg)


    • 分治时递归和处理中心的顺序可以是任意的,可以按照具体情况选择,以 简化复杂度。

    • 快速排序的期望复杂度:

    [T(n)=frac{1}{n}sum_{i=1}^n[T(i-1)+T(n-i)]+n-1=frac{2}{n}sum_{i=0}^{n-1}T(i)+n-1 ]

    [ncdot T(n)=2sum_{i=0}^{n-1}T(i)+n(n-1) ]

    [(n-1)cdot T(n-1)=2sum_{i=0}^{n-2}T(i)+(n-1)(n-2) ]

    [ncdot T(n)-(n-1)cdot T(n-1)=2T(n-1)+2(n-1) ]

    [ncdot T(n)=(n+1)T(n-1)+2(n-1) ]

    [frac{T(n)}{n+1}=frac{T(n-1)}{n}+frac{2(n-1)}{n(n+1)} ]

    [F(n)=frac{T(n)}{n+1}=sum_i^nfrac{2(i-1)}{i(i+1)}leq sum_i^n frac{2}{i}=2ln n ]

    [T(n)=O(nlog n) ]

    对于期望复杂度经典的证明方法,乘上(n)再错位相减。


    • 定理:期望为(O(f(n)))的复杂度退化到(O(g(n)))的概率小于(frac{f(n)}{g(n)}),而且这个上界非常宽松,大多数时候都达不到。

    • (O(n))找第(k)

    考虑快速排序的过程,按某个中间值分成两半,然后找对的一边递归下去。期望(O(n)),然而最劣是(O(n^2))

    发现最劣的情况在于每次都划分出一个大小为(1)的子问题。

    可以把原序列分成(5)份,排成一个(5 imes frac n5)的表格。对每一列找出中位数,然后找到列的中位数,从这个位置划分,可以保证每次问题规模最少降低(O(frac{3}{10}n))

    然而没什么用,因为常数巨大。

    给我们的启发意义在于,我们可以通过一些(大)合(常)理(数)手段划分分治中心,从而降低复杂度。


    • 分治fft

    • 三维偏序:cdq分治


    • (n)个红点,(n)个黑点,没有重复或三点共线。求一个红黑点的完美匹配,使得连线互不相交,保证有解。(n leq 10^4)

    sd省集讲过,然而我又忘了。

    提示:对于任意这样的(2n)个点,解一定存在。

    证明:只需要找到总长度最小的一种方案,一定不会有交点。

    一定可以找到一条直线把点集分开,使得两边红黑点个数均相等。考虑坐标最小的某个点为原点,把剩余点按照极角排序,由于不存在三点共线,则一定有这样的位置,恰好使两边相等。

    最劣是(O(n^2log n)),但是每次旋转一个角度,随机选点跑得很快,(O()能过())


    • (n)个整数(a_i),求(min_{i<j}{ (j-i)^2+(sum_{k=i+1}^j a_k)^2 })(nleq 10^5)

    (a_i)取个前缀和(S_i),发现把((i,S_i))看作一个点,就是一个平面上距离。平面最近点对即可。我一开始想分治+斜率优化来着。


    • 给定一棵树,问有多少个大小为(k)的点集,使得存在节点(u),使得任意一个(vin S),有(dis(u,v)leq L)(nleq 10^5)

    对于一个点集(S),满足条件的点构成一个连通块。树上连通块点数-边数=1,所以对于每个点、每条边分别统计满足条件的点集容斥一下即可。

    统计点集相当于对每个点(或边建出来的虚点)统计距离不超过(L)的点数,然后算个组合数就好了。邻域是经典问题,点分树就好了。


    • (1)为根的二叉树,对它任意一个包含(1)的连通块,给连通块内每个点赋一个权值(w_i),块外的点权值为(0),每个点的权值满足(w_igeq sum w_{son_i},w_1=x),求所有连通块的所有(w_i)的方案的和。(nleq 10^5,xleq 10^{18})

    (b_i=w_i-sum w_{son_i}),则原条件等价于(b_igeq 0,sum b_i=x)。设连通块大小为(m),则它的权值就是(C(x+m-1,m))

    于是问题变成统计以(1)为根,大小为(min[1,n])的连通块个数。

    这个若干天前讲过,求生成函数,树剖后分治fft即可。所以二叉树这个性质有什么用


    “动态点分治模板题,大家一定都做过,不用讲了。”

    点分树支持动态添加叶子,需要像替罪羊树一样重构。


    • 有向图(G),支持动态加边,求每次加边后((u,v))数,使得((u,v))互相可达,允许离线。(n,qleq 10^5)

    等价于对每条边((u,v)),统计((u,v))是什么时候开始相互可达的,然后用并查集计算即可。

    整体二分。设(solve(l,r,S))表示(S)里所有边都是在([l,r])时间段开始相互可达的。(在执行这个函数之前,且所有加入时间在([1,l))的,且在(S)内的边均已加入并缩点完毕,孤立点被删除。)

    我们把(S)([l,mid])的边都加入然后缩点,即可据此把(S)分为两部分,递归即可。右边可以直接递归,左边需要对缩点可回退化一下。代码很不可写。只对涉及到的点进行计算,单次递归复杂度是(O(|S|))的,每条边只会被计算(O(log))次。


    • 给定一个(w imes h)的网格,每次允许向右、上、下走,都有对应的权值,求左边一列每个点到右边一列每个点的最短路长度和。(w imes hleq 2 imes 10^5)

    维护从左上角出发的最短路径树。

    发现起点向下移动的时候,每个点在树上的父亲是逆时针单调旋转的,且最多变(2)次。

    对于一个时间区间([l,r]),如果一个点没有变父亲,它们是可以缩起来的。然后就和上一题一模一样了。


    • 离线求逆元

    类似阶乘逆元的求法,求前缀积然后反向递推回去即可。复杂度(O(n+log p))


    • 树上并查集

    树上分块+四毛子,块大小(O(loglog n)),可以做到线性。


    • 离线LCA

    Tarjan+并查集实现。

  • 相关阅读:
    Mongodb基础知识笔记
    使用pillow生成分享图片
    网页文字竖排的几种实现方式
    2019-07-13月亮拍摄
    6. 从尾到头打印链表[java]
    Linux设定终端Console命令回显状态
    bash ssh的登录信息与欢迎信息
    使用putty配套工具pscp实现windows与Linux平台间文件传送[Linux]
    5. 替换空格[java]
    4. 二维数组中的查找[java]
  • 原文地址:https://www.cnblogs.com/suwakow/p/11375074.html
Copyright © 2011-2022 走看看