- 感觉这一部分理解地比较困难,比较久,莫非是文化学太久脑子生锈了。。。
- 引入了一个名叫势能的概念,我理解的主要思想是说把一个势能为0的线段树节点 \([L,R]\) 打上标记,这样以后就可以对它进行整体处理,再计算原本有的势能以及会增加的势能得出一个复杂度合法的方案
- 把势能按照重力势能去看待则它<=初始势能+均摊势能的和 区间极差
- C - 基础数据结构练习题
- JLY大神通过极差来去弄它们之间的关系,并发现若对于最大值为 \(y\) 最小值为 \(x\) 的区间开根,开完后的 \(y_1-x_1 <= \sqrt{y-x} + 1\)
- 故我们能得到总势能 \(\sum_{[L,R]} log log (y-x)\)
- 我们再特殊讨论一下极差为1的情况,发现如15,16它们会变成3,4这时候极差没有改变,故我们可以 通过极差是否改变来选择是否打标记,像这种极差没有改变的直接打减法标记,其他的暴力开方
- 故我们考虑如何看待区间加操作,首先显而易见的如果一个区间是完全相同的话那么可以直接打标记,反之则极差最多增加\(v\) 故一个区间在线段树上由 \(log_{n}\) 个节点组成,故我们可以得到它所增加的势能为 \(q \cdot log_{n} \cdot \log \log_{v}\)
- 故我们总的时间复杂度就是 \(O (N \log \log v + q \cdot \log_{N} \cdot \log \log_{v})\)
- 代码一开始写的比较复杂,写到一半进行了调整。
- B - 市场
- 还是看差值,初始的势能是 \(N \log_{N}\) 会增加的势能是 \(N \log_{N} \log_{N}\) 然后同理做即可。(8,7像上述的方案一样处理)
- D
- 三个操作
- 区间赋值
- 设 \([L,R]\) 的 \(mex\) 为 \(w\) 则将 \([L,R]\) 中的所有数加上 \(w\)
- 区间求和
- 对于一个修改区间,我们依次找到该区间的最小值,并把线段树区间内等于最小值的叶节点的所有数加上INF。重复以上过程,直到找到mex,再还原叶节点并打上加法tag。(注:还原的时候只要这个区间内的所有数都大于INF就让这个区间整体减去一个INF即可还原)
- 对于区间加上 mex 的操作我们能发现对于小于 \(mex\) 的数进行这个操作的时候至少会翻倍!故我们能发现一个数最多进行 \(log_{N}\) 次翻倍,一次翻倍的代价是找出那个叶子节点进行翻倍 O(\log_{N})
- 复杂度为 \(O(N \log_{N} ^ 2)\)
- 对于区间赋值操作我们可以打一个区间赋值tag,在整个区间已被推平时不继续遍历即可。是 \(O(N \log_{N}^3)\) 的,JLY大神说可能需要仔细分析,但是我不会分析我也没找到分析这个的题解,加上这个复杂度本身就是跑不满的,主要还是学习均摊的这种思想,所以就这样吧。
-
如何判断是均摊
- 一个势能+一个标记 (当标记不能解决,分块与单边递归不能解决时可用)
- 经常与区间极差有关(区间最大值-区间最小值)
- E
- 势能是 \(\sum_{[L,R]}\) 的不同数的个数
- 考虑对区间 \([L,R]\) 取 \(\min(a_i,t)\) 这个操作如何实现。
- 若 \(t >= \max\) (即 \(t\) 比 \([L,R]\) 区间中的最大值还要大或等于) 那么不用管
- 若 \(t < \max\) 且 \(t > \sec\) 即 \(t\) 比 \([L,R]\) 区间中的最大值小但是比次大值大,则我们用一个 \(tag\) 记录一下最大值要减多少
- 若 \(t <= \sec\) 即 \(t\) 比 \([L,R]\) 区间中的次大值小,那么 [L,R]中的不同数的个数至少减1,暴力去修改即可。
- 初始势能 \(N \log_{N}\) ,考虑修改操作的第三种 \(t<=sec\) 的我们能发现它每遍历到一个节点的势能至少减一,故时间复杂度为 \(O(N \log_{N})\)
- 若加上一个区间加的操作
- 对于势能的定义为 \(\sum_{[L,R]}\) 左右两子节点的 \(max\) 值不相同
- 那么我们通过 画图可以发现
- 若左右的最大值相等,且次大值在一边则只会单边递归
- 若最大值和次大值都在一边,也只会单边递归
- 若出现最大值和次大值在异侧的情况,则两个都会递归,但会使得势能减一,我们不妨把势能减一的功劳归到叶子节点的头上,故 势能减一需要 O(\log_{N}) 的复杂度
- 其实这里我理解了很久不明白第一种情况的时候若是取min的 \(t\) 很小不仅仅比次大值小,还比另一边的次大值小不也要递归两侧,后面发现这种情况其实可以分裂来看,或者说它在后面的孙子节点上也会对势能进行减法。
- 故我们可以得到最初的势能为 \(O(N)\) 若进行一次加法则势能最多增加 \(O(\log_{N})\),又因为势能减一需要 \(O(\log_{N})\) 的复杂度
- 故总的时间复杂度为 \(O(N \log_{N}^2)\)
- F
- 绕了好久啊,搞了好久才get到JLY在说什么
- 维护每个版本(1-Q)目前的最小值(开个线段树)
- 从 \(n -> 1\) 的顺序去考虑每个数
- 假如 \(i\) 保持 \(a_i = x\) 在时间 \([L,R]\) 则对于线段树上的区间 \([L,R]\) 计算大于 \(x\) 的数的个数并对 \(x\) 取 \(min\) (这个操作最多有 \(Q\) 次因为 \(a\) 数组最多有 \(Q\) 次修改)
- 像上述所说的 吉斯机线段树 一样,维护区间最大值 \(mx\) 和次大值 \(sec\) 和最大值的个数 \(len\)
- 考虑势能为 \(\sum_{[L,R]}\) 数的种类个数 (原势能为 \(N \log_{N}\))
- 若 \(x >= mx\) 则不管
- 若 \(sec < x < mx\) 则维护 \(tag\) 表示最大值减了多少
- 否则 \(x <= sec\) 则去修改,势能减了1(数的种类减少了1) (考虑最多会有原势能次这种操作)
- 故我们可以得到一个 \(O(N \log_{N} + Q \log_{N})\) 的做法
- G
- 普通矩阵乘法 两个矩阵 \(A_{n,m}, B_{m,p}\) 相乘得到 \(C_{n,p}\) 满足 \(C_{n,p} = \sum A_{n,i} B_{i,p}\)
- 广义矩阵乘法(常用于处理区间最值和历史最值)
- 定义 \(C_{n,p} = \max(A_{n,i} + B_{i,p})\)
- 然后我们将区间赋值操作,区间加操作,历史最值操作对当前最值操作取 \(\max\) 这三个操作具象化成广义矩乘
- 定义 \(\begin{bmatrix}b \\a\\0\end{bmatrix}\) (\(b\) 为历史最大值,\(a\) 为当前最大值,然后用线段树维护即可)。然后 update 函数有个地方写太快忘记写 min(mid,ex) 了然后调了半个多小时。。。
posted @
2026-02-01 14:19
睡神本神
阅读(
2)
评论()
收藏
举报