首页 > 其他 > 详细

分治与分块

时间:2020-02-01 17:52:36      阅读:60      评论:0      收藏:0      [点我收藏+]

分治与分块

还没更完,,只是上课时的笔记,很多东西很多很杂。。得慢慢吸收吧。。

分治
  • CDQ 分治

    本质上是考虑左边对右边的影响,问题变成了先加入再查询的问题

    • 离线算法

    • 处理 D 维数点时间是 $ O(nlog^{D-1}n) $

      D 维数点用KDTree:$ O(n^{\frac{D-1}{D}}) $

      D 维数点用Bitset:$ O(\frac{Dn^2}w) $ *

    • 应用:

      加点,给定 $ a , b $ 查询最大的 $ ax+by $

      本质上是维护动态凸壳 *

      • 直接set维护

        记录全局变量,做插入的时候按照 x 比较,做询问按照斜率比较

        因为set里面x递增,斜率也递增

      • CDQ 分治

        solve( l , r ) ,先 solve( l , m ) solve( m + 1 , r )

        然后就变成了静态问题,左边点加进去,右边的询问。

        静态凸壳!

        右边斜率排序,然后类似归排扫一遍就好了。

    • CF 848C

      维护每个数字的位置和上一次出现的位置,价值是 i - pre i

      一段区间的价值就是 $ \displaystyle\sum_{l\leq i \leq r , pre[i] \geq l} i - pre[i] $

      本质上类似差分

      修改本质上只会修改 pre 指向这个点的,这个点,还有它的prev,只会改变三个值。

      带修改的二维数点本质上是三维数点,时间是一维。 $ O(nlog^2n) $

      可以写一下

    • uoj 50

      求解微分方程 $ f‘(x) = f^2(x) p(x) + 1 $

      算出来的式子是 $ \displaystyle \frac{1}{n} \sum_{0\leq i+j\leq n-1} f_if_jp_{n-1-i-j} $

      分治吧,貌似就是分治fft套路

      先solve( l , m )

      然后考虑新求出的左边的值对右边的贡献

      然后就要用 $ f_{l...mid} f_{0...r-l} p_{0...r-1} $ 卷起来

      然后就把 $ m+1...r $ 更新进 $ f_{m+1...r} $

      式子可能有点小锅,需要再推一下。。

  • 线段树分治(暑假讲的叫时间分治)

    • 离线动态图连通性

      把每条边的存活时间放到序列上,然后就可以在线段树上dfs,撤销并查集解决问题

      这里要按大小合并,才可以让撤销的量很少

      可以LCT维护删除时间的最大生成树,也是离线

    • 对每个物品,求不包含它的背包 方案数

      线段树分治

      solve( l , r , f ) f 表示 把 $ l , r $ 外面的物品加入的数组

      f_1 表示 f 加入 mid + 1 ... r 的物品

      f_2 表示 f 加入 l ... mid

      然后递归下去 $ O(nwlogn) $ 一个物品会被加入 $ logn $ 次

    • 城市建设

      修改边权,求MST和

      还是可以对时间建立线段树,求出每个边存活时间

      LCT 一个 log,线段树分治一个 log,很慢,不需要动脑子

      修改一条边边权实际上只会影响MST一条边

      随着修改MST变化是很少的

      $ solve(l,r) $ 表示 $ l , r $ 的修改

      整个MST只会改 $ O(r-l) $ 边,其他大多数边是不变的

      能不能把会变的边拿出来跑MST?

      假设边集(l...r修改的边)是 $ S $ ,先把其中边设置为 +inf

      把这些边和剩余的边跑MST,然后现在不在MST中的边就可以删除了。

      因为这些边只会变小,只会把MST的边给拖出来

      现在边数边成了 $ O(n + |S|) $

      然后再设置成 -inf,再跑一次MST,现在在MST中的边一定最后也在MST中

      点数变成了 $ O(|S|) $,因为这些边已经可以用并查集并起来了。

      而 $ n $ 其实是上一层的点数,也就是 $ O(2(r-l)) $

      所以这一层的复杂度也是 $ O(r-l) $ 的

      $ T(n) = 2T(\frac{n}{2}) + O(nlogn) $

      $ O(nlog^2n) $ 这里的 log 是排序

      有点难写吧(可以写一下

      核心思想:修改影响的边数量很少

  • 二进制分组

    • 二项堆

      一种可并堆。

      T_k 表示的堆是 $ T_{k-1} $ 再挂了个 $ T_{k-1} $ ,然后节点数量就是 $ 2^{k-1} $

      11个数字的二项堆就是一个 8+2+1的森林

      合并两个二项堆就是类似二进制+法。

      合并是 $ log $ 的

      删除元素,其实也是合并,比如从16的堆删除就是 1,2,4,8, 的堆和剩下的堆合并。

    • 维护向量序列,支持末尾加入元素,末尾删除元素,求 $ l,r $ 和 $ (x,y) $ 的最大点积

      二进制分组解决的问题往往是,重构很简单,插入删除很麻烦的东西。比如凸壳这种东西,重构直接做,但是插入删除很难。

      如果只有增加的话,加入当前有21个元素,我们记做三组 16 + 4 + 1

      每组都建一个数据结构,支持区间查询,并且重构很快(线性就很优秀),插入删除很慢。

      你往后面加入一个元素,就和前面一步一步合并(重构)过去,比如刚刚那个21的例子,加入一个元素就是 16 + 4 + 2

      这样的结构数量必然是 $ log $ ,如果在某个结构查询复杂度是$ Q(n) $ 那么查询复杂度就是$ Q(n)logn $

      重构的复杂度假如是 $ n $ 那么每一个元素最多会被重构 $ logn $ 次,所以,总复杂度是 $ nlogn $

      重构是均摊 $ logn $ 的

      既然支持区间操作,可以对每个区间建个线段树,暴力build线段树也是 $ nlogn $

      复杂度是 $ nlog^2n $ 的

      其实也可以看作建了一棵大的,点数是2的次幂的线段树,当一个点下面的所有叶子都被填了值才把它建出来。本质上是一样的。

      二进制分组怎么删除呢?其实整个序列如果画成一棵树的样子(大概就是版本树之类的?)删除就是往父亲跳,加入就是新加儿子。所以问题本质上就是给你棵树,求某个点到根上的一段的点积的最大值。

      树剖是 $ O(nlog^3n) $ 对询问排序可以去一个log,反正好像不优秀

      题解做法好像是点分

      直接线段树强行搞是不行的,你删除一个插入一个....在一个块的左右反复横跳就挂了

      其实可以搞成随机的,每个点随机一个权值如果比上一个小就合并。

      对于一个块被建出来,如果这个块有东西被删除了,就记个标记表示这个块是坏的。

      查询如果查到一个坏的块(节点)就到左右递归继续查。

      我们希望保证每层只有一个坏的块

      如果结尾一直在最后那个坏块动来动去没啥问题

      但是如果你的结尾移到了前一个块,那么意味着最后面那块被删光了,那么还是只有一个坏块

      但是如果结尾移到了后一个位置,下一个块被建了,那么我们可以直接重构前一个块。

      还不是很明白,想清楚了再继续写吧。。

      这个看起来比较清楚

  • 整体二分

    • 子矩阵查询 kth n 500 q 50000

      直接二分的话,需要查询子矩阵比某个数大的个数

      整体二分,就是拿所有询问一起二分

      我们需要看哪些询问权值是大于 $ \frac{w}{2} $ 的,哪些是小于等于 $ \frac{w}{2} $ 的

      这个比较简单的方法是把小于等于 $ mid $ 的标1,然后前缀和

      然后我们就把询问分成了 $ 0...\frac w 2 $ , $ \frac w 2 + 1 $

      就这样分治下去

      但是每一次分治 $ n^2 $ 肯定是不行的,必须做到每层 $ n^2 $

      每次分治其实我们只需要把 $ l...mid $ 加进去然后做查询

      对于每个询问就是二维数点的问题。

      其实貌似顺次递归来做,就直接是对的了吧。。

      所以对于分治到 $ l,r $ 复杂度就是 $ O(|A|+|Q|logn) $ $ A $ 为这里的点集

      复杂度是 $ (n^2+Q) log^2(n^2) $

    • 单点修改区间 kth

      二分到 $ l,r $ 把一个数字从 $ a $ 到 $ b $ 就是 $ x $ 这个位置 少 $ a $ 多 $ b $

      可以看自己以前的代码吧 $ nlog^2n $的

      ZOJ2112 这题由于空间限制只能整体二分

    • 给 $ l , r $ 的vector 放进去个 k 求 l , r kth

      整体二分就变成区间+了 貌似就是那个 任务查询系统 以前挂了好久的题

    • CF 102354 B

      给定 a , b 两个1...n 排列,求 $ c[k] = MAX_{(i,j)=k}|a_i-b_j| $

      $ c[k] = MAX_{(i.j)=1}|a_{ik}-b_{jk}| $

      其实我们只要求了 $ c[1] $ 问题就解决了

      因为 $ c[k] $ 本质 就是 $ a_k,a_{2k},...,a_{\lfloor\frac n k \rfloor} $ 和 $ b_k,b_{2k},...,b_{\lfloor\frac n k \rfloor} $ 来跑 $ c[1]$

      枚举 $ i $ 就要求最大的 $ b_j , (i,j) = 1 $,因为最大最小是对称的我们求最大的就好了。

      整体二分,分治到 $ (l,r) $,就是知道 $ a_i $ 的最大的值在 l,r 间。

      我们按照 值在 $ mid + 1...r $ 的下标是否存在与当前 $ a $ 互质的把 $ a $ 分成两份分别跑二分下去。

      然后问题就是,统计值在 $ mid + 1 ... r $ 的下表 $ j_t $ 是否存在与某个下标互质。

      对于 $ a_i $ 下标 $ i $,需要统计

      $ \displaystyle\sum_{j\in A}[(i,j)=1] $

      莫反一下

      $ \displaystyle \sum_{j\in A} \sum_{d|(i,j)} \mu(d) $

      然后我们可以枚举 $ d $ ,给每个 $ d $ 统计一下在 $ A $ 里面的倍数个数,并且把 $ \mu(d) \times cnt $ 放到作为它倍数的 $ i $ 里面。

  • 决策单调性
    就是存在最优的方案决策单调。一般都是打表找的规律。

    首先,四边形不等式 $ w(a,d) + w(b,c) \geq w(a,b) + w(c,d) $

    假设有 $ i , k , l , j $ , 如果决策不单调意味着 $ i $ 转移到了 $ j $ 而 $ k $ 转移到了 $ l $

    如果满足了上面那个式子,相交的两条边优于了包含的边,所以就满足了决策单调性。这大概就是实质了吧?

    • CF 321 E & 诗人小G

      下面是几种搞决策单调性的方法

      这里可能还需要再听一下

      $ solve( l , r , p , q ) $ 表示 i 再 $ l , r $ 最优决策是 $ p , q $ 之间

      我们可以先算 $ mid $ 位置的决策点 op 然后,就可以

      $ solve(l,mid,p,op) , solve(mid+1,r,op,q) $

      这样复杂度是 $ O(knlog_2n) $ 这样不容易挂。

      其实也可以二分单调栈。考虑我们如果求出了 $ dp[1] $ 那么后面最优都是从 1 转移过来

      现在求出了 2 , 从 2 转移最优的构成了一个后缀。于是我们可以用单调栈维护每个点可以决定的区间。先从后往前找看能不能整个替代,到达具体区间后再二分。复杂度也是一个 $ log $ 但但是不如前一个好写。

      其实是可以 $ O(nk) $ 的,然而我看不懂 SMAWK

    • 四边形不等式

      满足四边形不等式后,假设 $ dp[l][r] $ 决策点是 $ p[l][r] $,那么

      $ p[l][r-1]\leq p[l][r] \leq p[l+1][r] $

      其实本质就是交错的路径优秀于包含的路径

    • CF 868 F

      暴力分治,$ solve( l , r , p , q ) $

      分治下去的时候端点的移动总量是 $ O(r-l+q-p) $ 级别的。

      把指针从 $ p $ 移动到 $ mid $ 并且不断更新每个数字的出现个数,同时不断算 答案并且更新。

      建议看这个学一下再

    • IOI 2013 wombats

      假设是朝右朝下吧,不是很影响
      对于 R 这一维建立线段树

      决策是具有单调性的,路径有交叉可以通过调整变短

      如果结束点从上往下走,那么中转点必然也是从上往下走的

      复杂度是 $ O(c^2logclogr) $

      这个

    • IOI 2014 holiday

      首先,肯定不会反复横跳

      然后,结论就是 $ r $ 关于 $ l $ 是决策单调的。

      不太会证,这里引用下钟神的证明:

      设某个区间\([l,r]\)的答案为\(w(l,r)\)

      考虑反证,设\(l\)的最优右端点为\(r\)\(l+1\)的最优右端点为\(r'\),且\(r' < r\)

      那么我们有:
      \[ w(l,r) >w(l,r')\\w(l+1,r') > w(l+1,r) \]
      两式相加得到
      \[ w(l,r) + w(l+1,r') > w(l,r') + w(l+1,r) \]

      \[ w(l,r) - w(l,r') > w(l+1,r) - w(l+1,r') \]
      显然是不成立的,因为上述式子的意义实际上是将\((r',r]\)的元素加入\([l,r']\)或者\([l+1,r']\),带来的额外的贡献。由于加入的元素是相同的,而\([l,r']\)它可以去玩的天数更少,所以
      \[ w(l,r) - w(l,r') \le w(l+1,r) - w(l+1,r') \]

  • WQS 二分

    凸优化

    • Tree

      我们考虑给所有白色边加权,通过调权值可以让最优策略的白色边个数变化。

      通过二分调整权值使得最优策略正好需要need个白边

    什么情况这样二分正确呢?如果代价关于个数的图像是凸的

    若 $ f(x) $ 表示选择 $ x $ 个白边(上一个题)的代价

    条件就是 $ f(x+1) - f(x) \geq f(x) - f(x-1) $

    咋证明,我也不会,只会感性理解QAQ

    • 邮局

      如果权值满足四边形不等式,那 f 一定是凸的。

      所以二分权值,然后用那个单调栈的方法dp一下

      复杂度是 $ O(nlognlogv) $

      --- 开始掉线 ---

    • Rikka with K-Match

      没看太懂,后来再康康吧。。。wsl

    • 林克卡特树

      二分,搞个额外代价,虽然不会证明,但是它确实是凸的

    • 一个经典题

      操作A串(添加,删除,修改)使得AB循环同构

      不循环重构

      就是个 $ O(n^2) $ dp

      $ dp[i][j] $ 可以由 $ dp[i-1][j-1] + c_M$ , $ dp[i-1][j] + c_A $ , $ dp[i][j-1]+c_d $ 转移得到

      这个可以看成是平面图上的最段路

      路径上的每个点当成决策点,对起点分治,找 $ 0,\frac m 2 $ 到 $ n , \frac m 2 $ 的路径。

      这个路径上半部分的点只对上面的起点有用,下半部分的点只对下半部分的起点有用

      然后就可以分治下去做

      这大概就是广义的决策单调性 , 不仅可以用于dp

      (有点迷糊。。)

      循环同构复杂度是 $ n^2logn $ 的

    • 给定一个凸包,要选择 $ k $ 个点,使得围成面积最大

分治与分块

原文:https://www.cnblogs.com/yijan/p/12248974.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!