NOI 金牌导航

这里有些题因为太简单或不可做就没放。持续更新中。

1. 动态规划

1.2 数据结构优化 DP

B. 基站选址

\(f_{i, j}\) 表示考虑前 \(i\) 个村庄,选 \(j\) 个村庄作基站,\(i\) 必选时最小的总费用。考虑从决策点 \(k\) 转移到 \(i\),那么我们只需要处理位于区间 \([k + 1, i - 1]\) 中的村庄的覆盖情况。记这个值为 \(v\),那么有 \(f_{i, j} \gets f_{k, j - 1} + v + c_i\)

那么怎么做呢?考虑对每个村庄二分预处理出 \(l_i\)\(r_i\),表示可以覆盖它的最左端的村庄和最右端的村庄。那么我们只需要判断对于 \(p \in [k + 1, i - 1]\),是否有 \(l_p \leq k\)\(r_p \geq i\)

我们先考虑后者的满足情况再考虑前者。考虑将 \(p\) 的贡献挂在 \(r_p + 1\) 上。这样,我们每到一个 \(r_p + 1\),那么就意味着 \(p\) 不满足后者了,这时候我们考虑前者怎么维护。注意到前者对于所有 \(k \leq l_p - 1\) 都是不满足的,于是我们直接将区间 \([1, l_p - 1]\) 的 DP 值都加上 \(p\) 的代价即可。这样做显然是正确的。

需要注意的是,这题最后需要设一个虚村庄,即 \(n + 1\) 号村庄,否则显然是有问题的。维护的话直接上线段树就可以,时间复杂度 \(O(n \log n)\)

D. 免费馅饼

由于长和宽的范围都是 \({10}^8\),所以我们应该从馅饼的角度来考虑问题。

\(f_i\) 表示考虑前 \(i\) 块馅饼,强制拿第 \(i\) 块的最大分数。考虑从 \(j\) 转移到 \(i\)。显然,这需要满足 \(\lvert p_i - p_j \rvert \leq 2 \times (t_i - t_j)\)。拆开绝对值后你会得到两个式子,但需要分讨 \(p_i\)\(p_j\) 的大小,比较麻烦。但是容易证明我们只需要判断这两个式子是否同时成立即可。这样,原问题转化为了一个二维数点问题,直接做就行,时间复杂度 \(O(n \log n)\)

E. 优美玉米

显然,每次拔高的区间右端点一定为 \(n\)。否则将右端点改为 \(n\) 也没有影响。

考虑直接设计 DP。设 \(f_{i, j}\) 表示考虑前 \(i\) 个玉米,拔高了 \(j\) 次后的答案。显然,如果要从 \(i ^ {\prime}, j ^ {\prime}\) 转移到 \(i, j\) 只需要判断是否 \(j ^ {\prime} \leq j\) 与 $a_{i ^ {\prime}} + j ^ {\prime} \leq a_i + j $ 同时成立即可。

使用二维树状数组优化,时间复杂度为 \(O(n k \log n \log k)\),能过。

F. 地精部落

这题的 Trick 同 AT_dp_t,且后者严格强于前者,所以我们讲后者。

\(f_{i, j}\) 表示前 \(i\) 个数排列为 \(1 \sim n\),第 \(i\) 个数为 \(j\) 时的方案数。由于小于号和大于号是完全一样的,所以我们只考虑小于号的情况。

显然,\(f_{i, j}\) 只能被 \(k < j\)\(f_{i - 1, k}\) 转移。而对于任何一种转移,我们可以将大于等于 \(j\) 的数都加一,这样操作后的排列是合法的。所以 \(f_{i, j}\) 就等于所有 \(k < j\)\(f_{i - 1, k}\) 的和。

这显然可以前缀和优化,时间复杂度是 \(O(n ^ 2)\) 的。感觉也可以线段树合并优化,这样时间复杂度就是 \(O(n \log n)\) 的,但我不想写了。

1.3 决策单调性优化 DP

B. 土地购买

首先,如果存在包含关系,那么可以去掉小的那个矩形。那么,我们按照高度降序排序后,宽度一定是升序的。这样,我们选择的矩形组合一定是若干个区间。那么就是典型的连续段问题了,可以直接斜率优化。但这题的 DP 是有决策单调性的,所以也可以决策单调性优化。使用二分 + 单调队列的话时间复杂度就是 \(O(n \log n)\)

2. 字符串算法

2.2 后缀数组

A. 不可重叠串

显然在差分数组上做,那么只需要找到最长的出现两次且这两次不交的子串。

考虑二分答案,设这次二分到了 \(\text{mid}\)。考虑将 Height 数组中大于等于 \(\text{mid}\) 的值都标记为 \(1\),其他都是 \(0\)。这样,我们的两个后缀形成的排名区间一定是一段连续的 \(1\)。至于不交的部分,我们考虑处理出每个 \(1\) 连续段最前面和最后面的后缀,如果它们的距离大于 \(\text{mid}\) 就满足了不交的条件。

二分 check 显然是线性的,时间复杂度 \(O(n \log n)\)

G. 公共串计数

套路地,将 \(A\)\(B\) 拼接在一起建 SA,求出 Height 数组。

我们标记出 Height 数组中值大于等于 \(k\) 的位置,那么合法的后缀的排名一定形如若干个标记的连续段。这时,我们需要满足两个后缀不在一个串内,这可以染色解决。注意到两个后缀可以贡献多个子串,还需要使用单调栈统计答案。除建 SA 的部分时间复杂度线性。

3. 图论

3.7 双连通问题与圆方树

B. 铁人两项

先建出圆方树,考虑固定 \(s\)\(f\),求出 \(c\) 的数量。显然,在圆方树上圆点 \(s\)\(f\) 的路径中,方点代表的是必经过的点双,而圆点则代表必经过的割点。那么,对于一个必经过的点双,它内部的所有点都可以成为合法的 \(c\),所以我们可以将方点的权值赋为点双的大小。但是这样的话那些必经过的割点会算重,所以我们需要将圆点的权值赋为 \(-1\)。这样,我们只需要统计树上路径的点权和就行了。仿照树形 DP 的过程,考虑对每个点求出它的权值对答案的贡献即可。时间复杂度 \(O(n)\)

E. 战略游戏

建出圆方树。

对于两个关键点,显然,它们之间的圆点都是合法的。拓展这个结论,对于多个关键点来说,对于一个最小的能覆盖它们的联通块,这个联通块内的圆点(除了关键点本身)都是合法的。证明显然。

然后我们发现,这不就是虚树吗!于是写了个虚树,然后就挂了。其实它并不需要虚树,我们可以仿照建虚树的过程做。具体地,先将圆点的权值上移到边上,再按照 DFS 序排序,然后求出相邻的两个点路径中的圆点个数,再加上第一个点和最后一个点的,最后除以二,就是最小联通块中圆点的个数。证明的话是容易的,考虑每条边算的次数即可。

时间复杂度 \(O(n \log n)\),瓶颈在求 LCA 和排序。

4. 高级数据结构

4.1 左偏树

A. 派遣

选点在子节点与父节点之间没有继承关系,但删除不合法点则有继承关系,故考虑删除 \(c_i\) 较大的点。对每个点维护一个大根堆,继承时与父节点的合并。删除时只需要不断删堆顶即可。时间复杂度 \(O(n \log n)\)

B. 城池攻占

跟上一题一样的合并方式,只不过需要维护两个懒标记,参考线段树的即可。时间复杂度亦为 \(O(n \log n)\)

4.5 重量平衡树

B. 带插入区间k小值

替罪羊树套线段树谁写啊!分块链表是好的!

区间第 \(k\) 小的套路是同 最初方块 的。值域分块,维护块内数量和单点数量,再在序列上前缀和,查询就往上跳即可。

现在重点是插入操作,考虑分块链表。具体地,每个块对应链表的一个节点,插入就暴力插入,如果块长大于二倍应有块长就将这个点拆成两个点。实现都是不难的。

需要注意的是,插入可能插在最后面,所以要在最后面插入一个虚点,即 \(n + 1\) 号点。时间复杂度是 \(O(n \sqrt{n})\),不卡常,比树套树优秀多了。

4.8 笛卡尔树

A. 棋盘

先建出小根笛卡尔树。

考虑 DP。设 \(f_{u, i}\) 表示对于笛卡尔树上的点 \(u\),去掉 与它父亲 等量的最底下的若干行后放 \(i\) 个车的方案数。再设辅助数组 \(g_{u, i}\) 表示对于点 \(u\),去掉 与它 等量的最底下的若干行后放 \(i\) 个车的方案数。最后设 \(l\)\(r\) 分别表示 \(u\) 的左儿子与右儿子,\(t\) 为笛卡尔树的区间长度。

先求出 \(g_{u, i}\),显然有:

\[g_{u, i} = \sum_{j = 0}^i f_{l, j}f_{r, i - j} \]

再考虑求出 \(f_{u, i}\),枚举最底下的若干行的方法,有:

\[f_{u, i} = \sum_{j = 0}^i g_{u, i - j} {t \choose j} {h_u \choose j} {j!} \]

暴力算的话时间复杂度是 \(O(n^3)\) 的,但是这里两个式子都是可以卷积的形式,所以理论上时间复杂度可以优化至 \(O(n^2 \log n)\) 的。

B. 星座

首先,删除是不好办的,我们考虑保留一些星星,使得这些星星合法且权值和最大。

这道题不同于上一题,我们需要按照 \(a_i\) 建出大根笛卡尔树,

考虑 DP。设 \(f_{u, i}\) 表示考虑以 \(u\) 为根的子树,保留的星星最高的纵坐标为 \(i\) 时最大的权值和。设 \(l\)\(r\) 分别表示 \(u\) 的左儿子与右儿子。最后记 \(k = a_u\)

转移的话需要分类讨论,先考虑 \(i > k\) 的情况,此时显然有:

\[f_{u, i} = \max(f_{l, i} + \max_{j = 1}^k f_{r, j}, f_{r, i} + \max_{j = 1}^k f_{l, j}) \]

\(i \leq k\) 时,只需要将上式中的 \(k\) 替换为 \(i\) 即可。

其实,随着递归的回溯,\(k\) 是不断增大的。这意味这我们只需将 \(f_{u, k}\) 赋值为可能的前缀最大值即可,即:

\[f_{u, k} = \max_{j = 1}^k f_{l, j} + \max_{j = 1}^k f_{r, j} \]

使用线段树合并优化这个转移,时间复杂度为 \(O(n \log n)\)

5. 树上问题

6. 技巧与思想

6.3 分块算法

A. 区间众数

首先,维护第 \(i\) 个块内每个数出现次数和前 \(i\) 个块内每个数出现次数,这样我们可以轻松统计第 \(l\)\(r\) 个块内每个数出现次数。

再维护一个 \(f_{l, r}\) 表示第 \(l\)\(r\) 个块内的众数。预处理是简单的,对于一个 \(l\),将 \(r\)\(l\) 开始往右扫,扫到一个块就 \(O(\sqrt{n})\) 加入一个块。这样,这部分是总时间复杂度是 \(O(n \sqrt{n})\) 的。

每次查询区间 \([l, r]\) 时,设 \(l ^ {\prime}\) 表示 \(l\) 所在块的编号,\(r ^ {\prime}\) 表示 \(r\) 所在块的编号。同块或者相邻块直接暴力做,在这里不多赘述。如果不同块,显然区间众数要么为 \(f_{l ^ {\prime} + 1, r ^ {\prime} - 1}\),要么在边角料中出现过。这样,我们暴力枚举边角料即可。需要注意的是,枚举边角料时要加入第 \(l ^ {\prime} + 1\)\(r ^ {\prime} - 1\) 个块内数的个数。

时间复杂度为 \(O(n \sqrt{n})\),空间复杂度亦为 \(O(n \sqrt{n})\),不卡常。

7. 计算几何

8. 数学

8.7 莫比乌斯反演

A. 数对统计

即为求:

\[\sum_{i=1}^n \sum_{j=1}^m [\gcd(i, j) = 1] \]

直接莫反,上式等价于:

\[\sum_{i=1}^n \sum_{j=1}^m \sum_{d \mid \gcd(i, j)} \mu(d) \]

先枚举约数,上式等价于:

\[\sum_{d=1}^{\min(n, m)} \mu(d) \sum_{d \mid i } \sum_{d \mid j} 1 \]

化简,上式等价于:

\[\sum_{d=1}^{\min(n, m)} \mu(d) \lfloor \frac{n}{d} \rfloor \lfloor \frac{m}{d} \rfloor \]

直接整除分块即可。时间复杂度 \(O(n \sqrt{n})\)

B. 周期字符串

设函数 \(f(i)\) 表示长为 \(i\) 且循环节长度恰为 \(i\) 的字符串个数,函数 \(g(i)\) 表示长度为 \(i\) 的字符串个数,那么有:

\[g(i) = \sum_{d \mid i} f(d) \]

直接莫反,有:

\[f(i) = \sum_{d \mid i} \mu(d) g(\frac{n}{d}) \]

显然,\(g(i) = {26}^i\),这意味着我们可以通过快速幂来求出 \(g(i)\)。考虑 \(O(\sqrt{n})\) 枚举 \(d\),这时我们需要求出 \(\mu(d)\)。注意到 \(n \leq {10}^9\),直接杜教筛即可。时间复杂度玄学,反正能过。

8.8 杜教筛

B. 简单的数学题

真是简单。

考虑先枚举 \(\gcd(i, j)\) 的值,原式变为:

\[\sum_{k = 1}^{n} \sum_{i = 1}^n \sum_{j = 1}^n i j k [\gcd(i, j) = k] \]

显然,\(i\)\(j\) 都是 \(k\) 的倍数,那么上式等价于:

\[\sum_{k = 1}^{n} \sum_{i = 1}^{\lfloor \frac{n}{k} \rfloor} \sum_{j = 1}^{\lfloor \frac{n}{k} \rfloor} i j k^3 [\gcd(i, j) = 1] \]

直接莫反,上式等价于:

\[\sum_{k = 1}^{n} \sum_{i = 1}^{\lfloor \frac{n}{k} \rfloor} \sum_{j = 1}^{\lfloor \frac{n}{k} \rfloor} i j k^3 \sum_{d \mid \gcd(i, j)} \mu(d) \]

改变枚举顺序,依次为 \(k,d,i,j\)。显然,\(i\)\(j\) 也都是 \(d\) 的倍数,所以上式等价于:

\[\sum_{k = 1}^{n} \sum_{d = 1}^n \mu(d) \sum_{i = 1}^{\lfloor \frac{n}{kd} \rfloor} \sum_{j = 1}^{\lfloor \frac{n}{kd} \rfloor} i j k^3 d^2 \]

为了方便,我们定义下面的函数:

\[f(n, m) = \sum_{i = 1}^n \sum_{j = 1}^m ij \]

整理,原式变为:

\[\sum_{k = 1}^{n} \sum_{d = 1}^n k^3 d^2 \mu(d) f(\lfloor \frac{n}{kd} \rfloor,\lfloor \frac{n}{kd} \rfloor) \]

\(T = kd\),先枚举 \(T\) 再枚举 \(d\),上式等价于:

\[\sum_{T = 1}^{n^2} \sum_{d \mid T} (\frac{T}{d})^3 d^2 \mu(d) f(\lfloor \frac{n}{T} \rfloor,\lfloor \frac{n}{T} \rfloor) \]

显然,在 \(T > n\) 时是无意义的,那么上式等价于:

\[\sum_{T = 1}^{n} \sum_{d \mid T} (\frac{T}{d})^3 d^2 \mu(d) f(\lfloor \frac{n}{T} \rfloor,\lfloor \frac{n}{T} \rfloor) \]

\(d = \frac{T}{d}\),上式等价于:

\[\sum_{T = 1}^{n} \sum_{d \mid T} d^3 (\frac{T}{d})^2 \mu(\frac{T}{d}) f(\lfloor \frac{n}{T} \rfloor,\lfloor \frac{n}{T} \rfloor) \]

化简,上式等价于:

\[\sum_{T = 1}^{n} T^2 f(\lfloor \frac{n}{T} \rfloor,\lfloor \frac{n}{T} \rfloor) \sum_{d \mid T} d \mu(\frac{T}{d}) \]

由于 \(\varphi = \text{id} \ast \mu\),上式等价于:

\[\sum_{T = 1}^{n} f(\lfloor \frac{n}{T} \rfloor,\lfloor \frac{n}{T} \rfloor) T^2 \varphi(T) \]

考虑杜教筛。显然,上式中 \(f\) 函数的前缀和可以 \(O(1)\) 求,那么我们只需要考虑上式中去掉 \(f\) 的部分,即 \(\text{id}^2 \varphi\)。这在杜教筛中卷上一个 \(\text{id}^2\) 即可。时间复杂度 \(O(n ^ {\frac{3}{4}})\),能过。

8.9 快速傅里叶变换

A. 力

差卷积,分两部分卷,翻转一下即可,时间复杂度 \(O(n \log n)\)

posted @ 2025-04-09 12:03  Eliauk_FP  阅读(99)  评论(0)    收藏  举报