首页 > 其他分享 >「闲话随笔」势能分析法

「闲话随笔」势能分析法

时间:2023-01-12 22:37:16浏览次数:66  
标签:势能 right log phi 分析法 zig 随笔 left

「闲话随笔」势能分析法

点击查看目录

目录

这闲话已经被催了两天了,累死我了。

感谢 joke3579 帮我找到了 Tarjan 的论文虽然没看懂只截了一下里面的图。

语文考了 82,需要单独给语文老师发作业,很闹心。

今日推歌:盲龙默虎 feat.洛天依 vs 言和

iKz 老师的《一年一度武斗大赛》系列是不是快要更了?

简介

一种挺神奇的分析时间复杂度的方法。

一个算法/数据结构单次操作的复杂度难以计算时可以用势能分析法。

分析

设第 \(i\) 次操作的时间复杂度为 \(a_i\),显然总复杂度为 \(\sum_{i=1}^{n}a_i\)。

构造一个势能函数 \(\phi(i)\) 表示第 \(i\) 次操作后的势能,设 \(\Delta_{\phi(i)}\) 表示单次的势能变化,即 \(\Delta_{\phi(i)}=\phi(i)-\phi(i-1)\)。

设摊还代价 \(b_i=a_i+\Delta_{\phi(i)}\),则:

\[\sum_{i=1}^{n}a_i=(\sum_{i=1}^{n}a_i+\Delta_{\phi(i)})-\sum_{i=1}^{n}\Delta_{\phi(i)}=\sum_{i=1}^{n}b_i+\phi(0)-\phi(n) \]

不知道我在说什么,对不对?看起来啥用没有,对不对?

不对就怪了

实际上我们虽然无法算出具体的 \(a_i\),但是可以用未知数表示出来,这个时候构造一个优秀的势能函数,就可以巧妙地将 \(b_i\) 化为一个数或是求出其上限。

看看例题就都明白了。

例题

二进制计数器

题意:

一个二进制下的计数器,每次累加 \(1\),做 \(n\) 次累加,求操作的次数。

定义一次操作为一位上发生变化,因此每次累加 \(1\) 可能会带有多次操作。

设每次累加会有 \(x\) 位 \(1\) 变为 \(0\),那么 \(a_i=x+1\)(还会有一个 \(0\) 变为 \(1\))。

那么构造势能函数 \(\phi(i)\) 表示累加 \(i\) 次后数字里有多少个一。

显然 \(\Delta_{\phi(i)}=1-x\)。

然后就发生了一件神奇的事:\(b_i=(x-1)+(1-x)=2\)!

然后化简原式得到复杂度 \(2n-\phi(n)\le 2n\)。

单调栈

不会单调栈就来学这个是不是有点过猛了。

显然单调栈不用这么麻烦地分析,但确实可以这么用。

设每次操作会有 \(x\) 个元素弹出,\(1\) 个元素加入,那么 \(a_i=x+1\)。

那么构造势能函数 \(\phi(i)\) 表示当前栈内元素个数。

显然 \(\Delta_{\phi(i)}=1-x\)。

然后就发生了一件神奇的事:\(b_i=(x-1)+(1-x)=2\)!

然后化简原式得到复杂度 \(2n-\phi(n)\le 2n\)。

然后还发生了一件神奇的事:这个过程和上个过程居然没啥区别。

Splay

默认读者已经会 splay 了,不会的话去网上搜 或者等我平衡树学习笔记写完了再看

定义 \(x\) 为一棵 splay 上的一个节点,\(x'\) 为 \(x\) 旋一次后的位置,\(\left|x\right|\) 为以 \(x\) 为根的子树的大小,\(\phi_{j}(x)=\log_{2}\left|x\right|\) 为一次 splay 操作中第 \(j\) 次操作后节点 \(x\) 的势能,\(\Phi_j\) 为一次 splay 操作中第 \(j\) 次操作后整棵树的势能。

然后我们开始分析三种旋转情况的 \(a_i\):

  1. 旋上根(\(\text{zig}\)):

    屏幕截图_20230112_192746

    可以发现转一次只会有 \(x\) 和 \(y\) 的势能发生变化。

    显然 \(\phi_{j}(x)=\phi_{j-1}(y)\)。

    \[\begin{aligned} b_{\text{zig}}&=a_j+\Delta_{\Phi_j}\\ &=1+\phi_{j}(x)+\phi_{j}(y)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &=1+\phi_{j}(y)-\phi_{j-1}(x)\\ \end{aligned} \]

  2. 三点共线(\(\text{zig-zig}\)):

    屏幕截图_20230112_192904

    可以发现转一次只会有 \(x,y\) 和 \(z\) 的势能发生变化。

    显然 \(\phi_{j}(x)=\phi_{j-1}(z)\)。

    \[\begin{aligned} b_{\text{zig-zig}}&=a_j+\Delta_{\Phi_j}\\ &=2+\phi_{j}(x)+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)-\phi_{j-1}(z)\\ &=2+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ \end{aligned} \]

    注意到这个 \(2\) 长得很难看,尝试把它去掉。

    不难发现 \(\left|x\right|+\left|z'\right|+1=\left|x'\right|\),因此 \(\left|x'\right|^2>4\cdot\left|x\right|\cdot\left|z'\right|\),那么:

    \[\phi_{j-1}(x)+\phi_{j}(z)-2\phi_{j}(x)=\log_2\frac{\left|x\right|\cdot\left|z'\right|}{\left|x'\right|^2}\le\log_2\frac{1}{4}=-2 \]

    然后代入一下原式:

    \[\begin{aligned} b_{\text{zig-zig}}&=2+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &=2\phi_{j}(x)-\phi_{j-1}(x)-\phi_{j}(z)+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &=2\phi_{j}(x)-2\phi_{j-1}(x)+\phi_{j}(y)-\phi_{j-1}(y)\\ &\le3(\phi_{j}(x)-\phi_{j-1}(x)) \end{aligned} \]

    这样就求出了它的上限。

  3. 三点不共线(\(\text{zig-zag}\)):

    屏幕截图_20230112_192911

    比较像上面的式子。

    \[\begin{aligned} b_{\text{zig-zig}}&=a_j+\Delta_{\Phi_j}\\ &=2+\phi_{j}(x)+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)-\phi_{j-1}(z)\\ &=2+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ \end{aligned} \]

    然后由于 \(\left|y'\right|+\left|z'\right|+1=\left|x'\right|\):

    \[\phi_{j}(y)+\phi_{j}(z)-2\phi_{j}(x)=\log_2\frac{\left|y'\right|\cdot\left|z'\right|}{\left|x'\right|^2}\le\log_2\frac{1}{4}=-2 \]

    然后代入原式:

    \[\begin{aligned} b_{\text{zig-zig}}&=2+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &=2\phi_{j}(x)-\phi_{j}(y)-\phi_{j}(z)+\phi_{j}(y)+\phi_{j}(z)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &=2\phi_{j}(x)-\phi_{j-1}(x)-\phi_{j-1}(y)\\ &\le2(\phi_{j}(x)-\phi_{j-1}(x)) \end{aligned} \]

现在我们把三种旋转的摊还代价算出来了,问题变成了如何算出一次 splay 操作的摊还代价。

显然一次 splay 操作会进行若干次 \(\text{zig-zig}\), \(\text{zig-zag}\) 和至多一次 \(\text{zig}\),那么:

\[b_i\le\sum_{i=1}^{k}3(\phi_{j}(x)-\phi_{j-1}(x))=3(\phi_{k}(x)-\phi_{0}(x))=O(\log_2\frac{\left|x'\right|}{\left|x\right|})\le O(\log_2n) \]

然后由于 \(0\le\Phi_i\le n\log_2n\),\(-n\log_2n\le\Phi_0-\Phi_n\le n\log_2n\)。

所以总复杂度为:

\[\sum_{i=1}^{m}a_i=\sum_{i=1}^{m}b_i+\Phi_0-\Phi_n\le O(m\log_2n)+O(n\log_2n)=O((m+n)\log_2n) \]

\[\Huge\mathfrak{The\ End} \]

标签:势能,right,log,phi,分析法,zig,随笔,left
From: https://www.cnblogs.com/Keven-He/p/chat_20230112.html

相关文章

  • 开发一个微信小程序(2):编写博客园随笔列表
    上一篇介绍了如何通过博客园官方api获取随笔列表,本篇来实现把文章展示到小程序中 先来看一下最终的效果1、调用获取access_token接口如果想在小程序中成功调用接口,需要在......
  • 【随笔】思维技巧
    数学方向计数本质不同子序列,枚举每个子序列长度\(i\)以及首次出现结尾位置\(j\),后面的位置任意选,这\(i\)个位置任意选,为保证首次出现,其他位置上不能出现其右侧第一......
  • 从Bug中学习--Bug根因分析法
    来源:http://www.51testing.com/html/31/n-4456831.html一提起测试,大多数人很容易就会联想到Bug。的确,测试的日常工作离不开Bug,测试工作很重要的一部分就是发现Bug。但......
  • 【 随笔】 2023年1月12日 || 接近一个月未更新的学习记录: 开题答辩and旅游
    这段时间完成了两个比较重要的事情 分别是开题答辩和旅游。 因为博客园属于技术分享,所以将开题的大致思路整理一下放到博客上面。     ......
  • QtGui开发随笔
    Gui开发随笔QLabel、QCombobox这类控件在addWidget时如果设置了Qt::AlignRight就不会随窗口的变化而变化QComboBox显示数据量太大时加载比较耗时QComboBox*cb=new......
  • 技术随笔
    技术随笔来源:网络过滤器&拦截器https://www.bilibili.com/video/BV12W4y1W76H/?spm_id_from=333.999.0.0代码快速生成https://www.bilibili.com/video/BV1M......
  • 业务数据分析(三十一):产品分析(十)产品不同阶段的分析以及产品分析全流程(八)效果分析之常见
    业数据分析(三十一):产品分析(十)产品不同阶段的分析以及产品分析全流程(八)效果分析之常见效果跟踪分析法(二)页面跳转路径分析               ......
  • 一生一芯/NEMU PA3.1随笔
    保存上下文处理异常的时候需要保存寄存器内容(上下文的一部分),需要将这些内容保存下来。但是硬件不负责这些内容的保存,因此需要用软件代码来保存这些寄存器的值。riscv采用s......
  • 随笔 有所思20230107
    过2023年这一年26岁。工作的问题未解决。找份硬件测试的工作,看看。测试的要求其实还挺高的。想要有个屋子,有个书桌,有个书房。租房的每日的房租支出,一日34元的房租,电费......
  • 23 年 1 月随笔&闲话
    1.5:对“填鸭式教育”的一些看法下文内容可能有些敏感,但是我就要写。我不叛逆也总会有叛逆的人的。1月2日,当我看到学校发出的网课计划后,我沉没了。手机上那张排得满......