Skip to content

Commit d9a489b

Browse files
committed
add abc377
1 parent 30ec425 commit d9a489b

File tree

4 files changed

+540
-13
lines changed

4 files changed

+540
-13
lines changed

docs/algorithm/AtCoder/abc376.md

+13-13
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
???+ Abstract "题目大意"
4141

4242
有一个环,环上有 $N(3 \le N \le 100)$ 个位置。有两个棋子 `L` 和 `R`。初始的时候,`L` 在位置 $1$,`R` 在位置 $2$。你可以将棋子移动到环上相邻的位置,但是,在任意时刻都不能出现两个棋子公用
43-
43+
4444
给你 $Q(1 \le Q \le 100)$ 条指令,每条指令包含一个字符 $H_i$ 和整数 $T_i$。其中 $H_i$ 只可能是字符 `L` 和 `R`,$1 \le T_i \le N$。对于一条指令,如果 $H_i$ 是 `L`,表示你需要将 `L` 棋子移动到位置 $T_i$ 上。如果 $H_i$ 是 `R`,表示你需要将 `R` 棋子移动到位置 $T_i$ 上。对于每条指令,你 **只能** $H_i$ 一枚棋子。
45-
45+
4646
问:执行完所有指令最少需要移动多少步棋子?
4747

4848
<img src="https://img.atcoder.jp/abc376/bb6691e1c7281e4794b3fd94b256ba66.png" alt="img" style="zoom: 67%;" />
@@ -309,17 +309,17 @@
309309
???+ Abstract "题目大意"
310310

311311
有一个环,环上有 $N(3 \le N \le 3000)$ 个位置。有两个棋子 `L` 和 `R`。初始的时候,`L` 在位置 $1$,`R` 在位置 $2$。你可以将棋子移动到环上相邻的位置,但是,在任意时刻都不能出现两个棋子公用
312-
312+
313313
给你 $Q(1 \le Q \le 3000)$ 条指令,每条指令包含一个字符 $H_i$ 和整数 $T_i$。其中 $H_i$ 只可能是字符 `L` 和 `R`,$1 \le T_i \le N$。对于一条指令,如果 $H_i$ 是 `L`,表示你需要将 `L` 棋子移动到位置 $T_i$ 上。如果 $H_i$ 是 `R`,表示你需要将 `R` 棋子移动到位置 $T_i$ 上。在对于每条指令,如有需要,你 **可以** 移动两枚棋子。
314-
314+
315315
问:执行完所有指令最少需要移动多少步棋子?
316316

317317
<img src="https://img.atcoder.jp/abc376/bb6691e1c7281e4794b3fd94b256ba66.png" alt="img" style="zoom: 67%;" />
318318

319319
??? Note "解题思路"
320320

321321
本题和 B 题的区别就在于可以移动两枚棋子。B 题由于只能移动一颗棋子,移动的方式其实是固定的。但是可以移动两个棋子,每一次移动就会有顺时针和逆时针两种路径,可以这样处理指令的时候我们可以让另一枚棋子挪开。例如:现在 $L = 2, R = 4$,将 $R$ 移动到 $1$,可以让 $L$ 挪到 $N$,然后再让 $R$ 挪到 $1$。
322-
322+
323323
因此每一次移动都要考虑另一枚棋子的状态。定义 $dp[i][j]$ 表示处理完前 $i$ 条指令之后,另一枚棋子停在位置 $j$ 所需要移动的最小步数。转移的时候从前向后更新。注意另一枚棋子恰好停在 $T_i$ 上的情况。
324324

325325
??? Success "参考代码"
@@ -431,16 +431,16 @@
431431
??? Note "解题思路"
432432

433433
首先需要知道 $01$ 序列计算逆序数的一个推论,设有一段 $01$ 序列 $S = S_1 + S_2$,其中 $+$ 表示字符串连接。用 $R(S)$ 表示序列 $S$ 的逆序数,$C_0(S)$ 表示序列 $S$ 中 $0$ 的个数,$C_1(S)$ 表示序列 $S$ 中 $1$ 的个数,则 $R(S) = R(S_1) + R(S_2) + C_1(S_1) \times C_0(S_2)$。下面考虑如何构造答案。
434-
434+
435435
拓扑序列第一个点一定是根节点 $1$,考虑如何加入节点。可以发现:
436-
436+
437437
- 如果当前可以加入 $0$,那么加入 $0$ 一定会比加入 $1$ 更好。
438-
438+
439439
这个结论是非常显然的,于是考虑一种归并式的做法,将所有的 $0$ 合并到父节点上,被归并的节点相当于当父节点被选择后就一并选择。归并后,树上还剩下一些形如 $1000...$ 的节点。假设某个节点 $x$ 现在有子节点 $a$ 和 $b$,如果先归并 $a$,再归并 $b$,产生的逆序数就是 $R(x) = R(a) + R(b) + C_1(a) \times C_0(b)$,如果归并 $b$ 再归并 $a$,产生的逆序数就是 $R(x) = R(a) + R(b) + C_1(b) \times C_0(a)$,因此,当且仅当 $C_1(a) \times C_0(b) < C_1(b) \times C_0(a)$ 即 $\frac{C_1(a)}{C_0(a)} < \frac{C_1(b)}{C_0(b)}$,此时先归并 $a$ 更优。所以,维护每个节点里面 $0$ 和 $1$ 的数量,按照 $\frac{C_1(a)}{C_0(a)}$ 排序放到小顶堆里面就能选出下一个归并的节点。
440-
440+
441441
下面考虑推广 $\frac{C_1(a)}{C_0(a)}$,为了实现优先选 $0$,当 $C_1(a) = 0$ 时,小顶堆一定会弹出全是 $0$ 的序列,所以实际上不需要预处理所有将所有的 $0$ 合并的步骤。再考虑 $C_0(a) = 0$ 的情况,这实际就相当于全是 $1$ 的某个序列,这种序列一定是最后被添加的(也就是添加到末尾的),可以令 $\frac{C_1(a)}{C_0(a)} =+\infty$,就能保证最后弹出。
442-
443-
每一次合并的时候需要计算合并新序列所新增的逆序数,这同样可以通过 $R(S) = R(S_1) + R(S_2) + C_1(S_1) \times C_0(S_2)$ 来计算,增量的部分就是 $C_1(S_1) \times C_0(S_2)$。此外,合并的时候还需要维护一个并查集,堆实际也是烂删除堆,注意判断堆顶的元素是不是最新的。
442+
443+
每一次合并的时候需要计算合并新序列所新增的逆序数,这同样可以通过 $R(S) = R(S_1) + R(S_2) + C_1(S_1) \times C_0(S_2)$ 来计算,增量的部分就是 $C_1(S_1) \times C_0(S_2)$。此外,合并的时候还需要维护一个并查集,堆实际也是懒删除堆,注意判断堆顶的元素是不是最新的。
444444

445445
??? Success "参考代码"
446446

@@ -549,8 +549,8 @@
549549
??? Note "解题思路"
550550

551551
设某个搜索序列为 $P = (P_1, P_2, \cdots, P_N)$,令 $S = \sum\limits_{i=1}^Na_i$,则数学期望为 $E = \sum\limits_{i =1}^Ni \times \frac{a_i}{S} = \frac{1}{S} \sum\limits_{i =1}^Ni \times a_i$
552-
553-
这实际上可以转换成上面的 01 on tree 来解决,我们将包括根节点 $0$ 在内的节点 $i(0 \le i \le N)$ 初始的时候视为 $000...1$ 的序列,其中 $0$ 重复了 $a_i$ 次($a_0 = 0$),这样初始只有根节点的时候只有 $1$ 个 $1$,合并一个点 $i$ 就相当于增加了 $1 \times a_i$ 的逆序数,然后有 $2$ 个以,下一次合并点 $j$ 就会增加 $2 \times a_j$ 的逆序数,所以逆序数就等价于 $\sum\limits_{i =1}^Ni \times a_i$,所以问题就转化为 01 on tree。
552+
553+
这实际上可以转换成上面的 01 on tree 来解决,我们将包括根节点 $0$ 在内的节点 $i(0 \le i \le N)$ 初始的时候视为 $000...1$ 的序列,其中 $0$ 重复了 $a_i$ 次($a_0 = 0$),这样初始只有根节点的时候只有 $1$ 个 $1$,合并一个点 $i$ 就相当于增加了 $1 \times a_i$ 的逆序数,然后有 $2$ 个 $1$,下一次合并点 $j$ 就会增加 $2 \times a_j$ 的逆序数,所以逆序数就等价于 $\sum\limits_{i =1}^Ni \times a_i$,所以问题就转化为 01 on tree。
554554

555555
??? Success "参考代码"
556556

0 commit comments

Comments
 (0)