算法竞赛进阶指南 做题笔记

0x00

1.最短 Hamilton 路径

状压 dp。设 \(f_{S,i}\) 表示走过的节点状态为 \(S(0\) 为没走过,\(1\) 为走过 \()\),当前在点 \(i\) 时的最小代价,显然 \(S\) 的第 \(i\) 位必须为 \(1\)

那么 \(f_{S,i}= \min_{S \operatorname{and} 2^j =1,j \neq i } \lbrace f_{S \operatorname {xor} 2^i,j}+dis_{j,i}\rbrace \)

意思就是枚举在走 \(i\) 号点之前走的是哪个点,由上个没走过 \(i\) 的状态加上两点的距离转移过来。

注意这里点的编号都从 \(0\) 开始,初始时 \(f_{1,0}=0\),其余为正无穷,最后输出 \(f_{2^n-1,n-1}\) 即可。

2.费解的开关

注意到如果想要第 \(i\) 行上面的一行合法,点击方案是确定的,所以第一行的点击方案确定后,就可以推出接下来的点击情况。

所以枚举第一行的状态 \(S\)\(S\) 的第 \(k\) 位为 \(1\) 就点,否则就不点。

如果想要字典序最小,注意到第一行确定后只有一种方案,所以第一行字典序最小就好了。

3.奇怪的汉诺塔

\(d_i\) 表示解决 \(i\) 个盘子三个塔的最小步数,显然 \(d_i=2^i-1\),不再赘述,\(f_i\) 表示解决 \(i\) 个盘子四个塔的最小步数。

那么有 \(f_i =\min _{1 \le j < i}\lbrace 2 \times f_j+d_{i-j}\rbrace\)

含义是先挪 \(j\) 个盘子,再挪 \((i-j)\) 个盘子,这 \((i-j)\) 个盘子只有三个柱可以用,最后再挪 \(j\) 个盘子到这 \((i-j)\) 个盘子上面即可。

\(f_{1}=d_{1}=1\)

0x10

1.序列

考虑 \(m=2\),这是经典贪心。排序后最小值肯定是 \(a_1+b_1\)。然后第二小可能是 \(a_1+b_2\)\(a_2+b_1\),第三小若第二小是 \(a_1+b_2\) 则可能是 \(a_2+b_1\)\(a_2+b_3\)\(a_2+b_2\),以此类推。每次只会改变一个数,因此用堆维护贪心,每次取出最优解并扩展一个数即可。但是这样 \((i,j)\) 的产生方式不唯一,考虑强制先增加 \(i\) 再增加 \(j\),用一个 \(flag\) 记录当前是否开始增加 \(j\) 了即可。

0x50

1.你能回答这些问题吗

最大字段和可以线段树维护。

对于一个节点 \(p\),维护它的 \(lmax,rmax,dat,sum\),表示它左端点必选的最大字段和,右端点必选的最大字段和,整段的最大子段和,和。

\[lmax_p=\max\lbrace lmax_{p \times 2},sum_{p \times 2}+lmax_{p \times 2+1} \rbrace \]

\[rmax_p=\max\lbrace rmax_{p \times 2+1},sum_{p \times 2+1}+rmax_{p \times 2}\rbrace \]

\[dat_p=\max\lbrace dat_{p \times 2},dat_{p \times 2+1},rmax_{p \times 2}+lmax_{p \times 2+1}\rbrace \]

2.区间最大公约数

区间带修 gcd 不好直接线段树,考虑差分一遍那么 gcd 不变,这样修改好做一些。

查询的时候就是 \(\gcd(a_l,Q(l+1,r))\) 即可,对这个 \(a_l\) 还得专门开个树状数组维护。

3.磁力块

对于这个最多的,我们可以执行以下 BFS 框架:每次把能被吸引的磁铁全部吸过来,然后删掉当前磁铁。

能被吸引的限制有两维,考虑排序一维数据结构维护另一维。比如我们按照质量排序,那么每次只需要考虑距离。大部分数据结构方便的是统计数量,但这里要确实找出编号,考虑分块。

按距离排序后以 \(B\) 分块,每块再以距离排序,那么我们每次可以找到一个 \(k\),使得前 \(k-1\) 块的所有质量全都合法,\(k+1\) 及以后的块全都不合法,其实就是找第一个满足质量最大值大于磁力的块。

对于前面的块,合法的都是一段前缀。因为这是个 BFS,所以每个位置只要更新一次,所以对于每个块维护个指针 \(L\),表示这个块的前 \(L-1\) 个元素已经用过了。每次从 \(L\) 扩展,走遍这 \(k-1\) 个块均摊复杂度是 \(\mathcal{O}(B)\)。第 \(k\) 个块暴力,vis 标记还是要打。时间复杂度也是 \(\mathcal{O}(B)\)

看样子直接令 \(B=1\) 最优?但是遍历前 \(k-1\) 个块还有 \(\mathcal{O}(\frac{n}{B})\) 的复杂度。好像可以令 \(B=1\) 然后上个并查集做到 \(n\alpha(n)\),先咕着。

4.最大异或和

首先做前缀和,然后每次就是一个 \(S_n \oplus x \oplus S_{p-1}\),那么就是在 \([l-1,r-1]\) 中找一个 \(p\),使得 \(S_n \oplus S_p\) 最大。

直接仿照主席树,每次新建一侧的儿子,另一侧的复制同时维护 \(cnt\) 即可。注意 trie 的构造是非递归的,那么开始时新建的根会被多次更改,因此要专门开变量存一下。如果 \(l=1\) 那么会算到负数,但其实只比 \(l=2\) 多了一个全选的决策,比较一下即可。

5.Fotile 模拟赛 L

求出前缀和后直接枚举右端点然后用 trie 复杂度是 \(nm\log V\) 的,反正在 Acwing 的机子上过不了。

没有修改,考虑预处理答案,但又不能太预处理,不然空间就已经爆了。考虑以 \(B\) 分块,预处理出整块的答案,大部分的分块整块预处理就是枚举左边块编号,再向右扩展,更新。这部分复杂度是 \(\mathcal{O}((\frac{n}{B})^2 B \log V=\frac{n^2\log V}{B})\)

散块简单暴力即可,但是如果做最右边的块的时候枚举前面的所有数插到 trie 里又不行了,所以提前建好一个可持久化 trie 即可。细节:\(l<r\)

0x50

1.饼干

\(f_{i,j}\) 表示考虑了前 \(i\) 个人,分配了 \(j\) 个饼干时的最小怨气,那么答案为 \(f_{n,m}\)。这个东西没法直接计算,所以我们考虑上一点手段。

考虑已经确定了一种饼干数量的分配方式,那么显然贪婪度大的孩子需要得到更多的饼干,用贪心交换可以证明这一点。

那么我们先把孩子按贪婪度排序,分配的饼干数一定是一个单调不增的序列。考虑给第 \(i\) 个孩子分几块饼干,可这样还是不好算,再进行一个转化。

  • 如果第 \(i\) 个孩子的饼干数大于 \(1\),那么可以考虑将这 \(i\) 个人都少分配一块饼干,这样相对大小关系不变从而怨气值也不变,此时 \(f_{i,j}=f_{i,j-i}\),对于每个 \(i\)\(f_{i,j}\) 是随着 \(j\) 的增大而计算的,所以没有问题。

  • 如果第 \(i\) 个孩子的饼干数为 \(1\),则可以考虑有多少个孩子得到了一块饼干。即枚举一个 \(k\)\(k\) 后的孩子都只有 \(1\) 块饼干,则第 \(i\) 个孩子产生的怨气值就是 \(k \times \sum_{X=k+1}^i g_X+f_{k,j-(i-k)}\)

综上,经过一系列转化,我们得到:

\[f_{i,j}=\min(f_{i,j-i}[j>i],\min _{\max(i-j+1,0) \le k <i}\{k \times \sum_{X=k+1}^i g_X+f_{k,j-(i-k)}\} \]

输出方案与其他题一样,记下选定 \(f\) 数组的两维的值即可。

时间复杂度 \(\mathcal{O}(n^2 m)\)

2.连通图

\(f_i\) 表示 \(i\) 个点的无向连通图个数。

这个是不好算的,考虑容斥成所有减去不联通的。

\(i\) 个点的无向连通图共有 \(2^{\frac{i(i-1)}{2}}\) 个。

枚举 \(1\) 号点所在的连通块大小 \(j\),那么 \(f_i=2^{\frac{i(i-1)}{2}}-\sum_{j} f_j \times \binom{i-1}{j-1} \times 2^{\frac{(i-j)(i-j-1)}{2}}\)

傻卵题,还要高精度。

posted @ 2024-01-25 11:07  aCssen  阅读(31)  评论(1)    收藏  举报