闲话 22.8.8

闲话

回学校了。

发现muel在某个题库的头像是小祖宗
!我回家居然没看到她的切片
回家的日常:鼠家片、狼羊片、扇子片、狸片、豹片、蝙蝠片、鼠标片、debu片、白菜片、奇奇怪怪的片、果蝇片

?为什么我在无意识地哼《随便啦》
这歌前奏确实好听 但我确实只听过一遍
火锅p就是nb(

所以说今天在路上听了《两个人的》
于是放一下 虽然很短但是很舒缓平和
是序曲该有的感觉呢

两个人的序幕

もし幸せな物語が見たいなら
如果你想看一个幸福的故事
帰ったほうが
回去会比较好
良いかもしれない気が
我觉得这样可能会好些
しなくもないわ
也不是不可以

まあでもここまで来たのなら
不过既然已经来了
覗いて往けば良いさ
那就悄悄看一眼就好
月並みにはここまで
因为并不是
歩けなかったろうから
每一次都会走到这里来

ふたりの ふたりの
两个人的 两个人的
ふたりの ふたりの
两个人的 两个人的

そのスープ
那份汤
温かいうちに飲むのが良いよ
还是趁热喝比较好
冷めた方がお好きとか
如果你不是那
そういう人じゃなけりゃ
喜欢喝冷汤的人的话

その本が気になるのならば
如果你喜欢那本书
読んでも良いよ
你也可以拿来读
はるか遠い銀河の
只是关于遥远银河的
なんでもない話だ
无关紧要的故事罢了

だけどその前に
不过在那之前
ふたりのことが知りたいのなら
如果你想了解我们二人的话
君もどんな人生だったか
也希望你能告诉我
話してほしい
你度过了怎样的人生

ふたりの夢を夢を見せよう
让我们梦见两个人的梦想
夕焼けに染まったなら
若天空被晚霞染红
息を止めてくれ
还请屏息静赏

这是不是预示着我以后会更多的推《两个人的》专辑里的歌呢?敬请期待
当然一些杂歌也被提上日程了

话说回来我没做博客主题的手机适配(因为不会而且懒得写)
所以能用电脑尽量用电脑吧(我也不知道我是给谁说的)

启发式

启发式合并的核心,就是操作相对小的部分,不动大的部分。
假设有 \(n\) 个元素被随机分成了 \(m\) 个集合,进行 \(m-1\) 次操作,每次操作选定两个集合,把其中一个的元素全部插入另一个集合。总存在一种方案使得插入次数为 \(O(n \log n)\),这种方案即每次将小集合中的元素插入大集合。

证明如下:
我们观察每个元素插入前后对应集合的大小。由于每次将小集合内的元素并入大元素,因此小集合大小定小于等于合并后集合的 \(\frac 1 2\)。因此对任意一个元素,每进行一次插入,所在集合大小至少翻倍。显然有这样的插入最多进行 \(O(\log n)\) 次。对每个元素施分析得,总复杂度为 \(O(n \log n)\)。 $ \square $

因此我们可以使用这样的策略对集合合并进行优化。

可并(?)

一开始有 \(n\) 个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:

  1. 将第 \(x\) 个数和第 \(y\) 个数所在的小根堆合并(若第 \(x\) 或第 \(y\) 个数已经被删除或第 \(x\) 和第 \(y\) 个数在用一个堆内,则无视此操作)
  2. 输出第 \(x\) 个数所在的堆最小数,并将这个最小数删除(若有多个最小数,优先删除先输入的;若第 \(x\) 个数已经被删除,则输出 \(-1\) 并无视删除操作)

当然这是可并堆的板子。但我们也可以使用 \(O(n \log^2n)\) 的复杂度过去。具体地,我们使用启发式合并,每次将小堆合并入大堆,并查集维护元素所在堆编号。可以发现,进行了 \(O(n \log n)\)\(O(\log n)\) 插入,复杂度正确。

给定 \(n\) 个集合,第 \(i\) 个集合内初始状态下只有一个数,为 \(i\)。有 \(m\) 次操作。操作分为 \(3\) 种:

  1. 1 a b 合并 \(a,b\) 所在集合
  2. 2 k 回到第 \(k\) 次操作(执行三种操作中的任意一种都记为一次操作)之后的状态
  3. 3 a b 询问 \(a,b\) 是否属于同一集合,如果是则输出 \(1\),否则输出 \(0\)

当然这是可持久化并查集的板子。但我们也可以讲讲复杂度维护的方式。我们发现,如果你想在可持久化结构里改变形态,那不是MLE就是TLE。于是可持久化并查集不可能使用路径压缩。
因此我们使用另一种方式:按秩合并,或者按大小合并。每次我们将深度/大小小的合并入大的里面。最深节点的深度为 \(O(\log n)\)

证明一下:
我们观察单个元素在每次合并前后对应的深度。由于每次将小集合并入大元素,因此小集合大小定小于等于合并后集合的 \(\frac 1 2\),显然有这样的合并对每个元素最多进行 \(O(\log n)\) 次。而且对任意一个元素,每进行一次合并,深度至多增加1。因此每个元素的深度最多为 \(O(\log n\))。 $ \square $

有的时候我们需要把一个序列分成两个小序列,然后左右区间的信息合并一下。怎么合并?用启发式的思路,我们需要将小区间合并入大区间。

dsu on tree

desu on tree

又称树上启发式合并。
我们发现,上面的两个证明都是找到了对于每个点只有 \(O(\log n)\) 个的对象,然后暴力合并。我们又发现,似乎每个点到根只有 \(O(\log n)\) 条轻边。于是我们就可以继承重儿子的信息,遍历轻儿子求解,总复杂度确实是 \(O(n \log n)\) 的。

CF600E

有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树。每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\)。如果一种颜色在以 \(x\) 为根的子树内出现次数最多,称其在以 \(x\) 为根的子树中占主导地位。显然,同一子树中可能有多种颜色占主导地位。你的任务是对于每一个 \(i\in[1,n]\),求出以 \(i\) 为根的子树中,占主导地位的颜色的编号和。
\(n\le 10^5,c_i\le n\)

考虑启发式。对每个节点维护一个桶,记录最大值和编号和。然后每个节点开一个桶会炸内存。我们考虑用一个桶维护所有值,当所在位置是轻儿子时直接清空桶,所在为重儿子时不清空而继承。然后就能过了。

posted @ 2022-08-08 20:07  joke3579  阅读(74)  评论(7编辑  收藏  举报