AtCoder Beginner Contest(ABC) 247 A~G 题解
点击各题标题可以跳转到原题。
A - Move Right(Difficulty: 14)
Statement:将长度为 $4$ 的 01 串整体右移一位。
Solution:这个有什么好说的吗
Code:https://atcoder.jp/contests/abc247/submissions/30847456
B - Unique Nicknames(Difficulty: 202)
Statement:
- 给 $n$ 个人的姓、名,问是否每个人都有别人所没有的姓或名。
- $n \le 100$,记最大串长为 $s$,有 $s \le 10$。
Solution:
- 算法一:对于每一个人的姓名,对其他人逐个枚举判断,$\mathcal{O}(n^2s)$。
- 算法二:用 std::map 存每个人字符串,枚举的时候看看姓、名是否只有自己出现。时间复杂度 $\mathcal{n \log n}$,有大常数。
- 算法三:用 Trie 存下所有的姓名串,记录末尾节点的访问次数。时间复杂度 $\mathcal{O}(ns)$,空间复杂度$\mathcal{O}(26ns)$。
Code:https://atcoder.jp/contests/abc247/submissions/30852679
C - 1 2 1 3 1 2 1(Difficulty: 149)
Statement:
- 有一个初始序列 $[1]$。
- 现在进行 $n$ 次操作,第 $i$ 次操作将自己复制一遍,拼到末尾,正中间再插入一个数 $i$。
- 问 $n$ 次操作后的数列。$n \le 16$。
Solution:
- 没什么好说的,直接模拟即可,数组不要开小了。
Code:https://atcoder.jp/contests/abc247/submissions/30854775
D - Choose Me(Difficulty: 468)
Statement:
- 维护 $Q$ 次操作,操作分两种。
- 1. 队尾插入 $c$ 个权值均为 $x$ 的球。
- 2. 从队头取出 $c$ 个球,并输出这 $c$ 个球的权值和。
- $Q \le 200000, \ c,x \le 10^9$。
Solution:
- 像维护队列那样,找一个指针,记录当前正在取第几个操作放进去的球,以及这一批球剩几个。
- 时间复杂度 $\mathcal{O}(Q)$。
Code:https://atcoder.jp/contests/abc247/submissions/30859907
E - Through Path(Difficulty: 1256)
Statement:
- 有一个长度为 $n$ 的序列 $a_1,a_2,...,a_n$。
- 给出两个数 $x,y$,问区间最大值等于 $x$,最小值等于 $y$。
- $1 \le n,a_i,x,y \le 200000$。
Solution:
- 二分/双指针 + 线段树/ST表都是经典问题,可以快速解决,但是时间复杂度至少带个 $\log$,码量也大。代码点这里。
- 这里简单讲下 $\mathcal{O}(n)$ 且很好写的做法:
- 从左到右枚举,对每个位置 $i$ 记录在自己以左,且分别等于 $x,y$ 的距离自己最近的位置 $u,v$。
- 再记录自己以左且最近的大于 $x$ 或小于 $y$ 的位置 $w$。
- 若 $\min(u,v)-w>0$,那么答案就累加 $\min(u,v)-w$。最后输出累加的和。
线性复杂度做法代码:https://atcoder.jp/contests/abc247/submissions/30895819
F - Cards(Diffyculty: 1697)
Statement:
- 有两个 $1 \sim n$ 的排列 $p_1,p_2,..,p_n$,$q_1,q_2,...,q_n$。
- 你可以选若干个下标 $a_1,a_2,...,a_m$,使得 $p_{a_1},q_{a_1},p_{a_2},q_{q_2},...,p_{a_m},q_{a_m}$ 构成的集合包含完整 $1 \sim n$ 的排列。
- 求方案数对 $998244353$ 取模的值。
- $n \le 200000$。
Solution:
- 我们按照 $p_i$ 大小把 $q_i$ 排序,这样 $p_i$ 变为 $1,2,...,n$,可以当下标用。设位置 $i$ 现在的值为 $c_i$
- 若 $c_i=i$,代表我们选了下标 $i$ 时只得到了 $i$。
- 若 $c_i \neq i$,相当于我们选下标 $i$ 时得到了 $i,c_i$ 两个值。
- 由于 $p,q$ 数组是两个排列,因此每个元素恰好会出现两次。
- 由于 $i$ 位置的值是 $c_i$,所以下标是 $c_i$ 的值肯定又指向了另一个数。不难发现,这样一直指下去一定会形成一个环。
- 那么这 $n$ 个值就被分割成了若干个大小不一的环。由于环与环之间是独立的,我们只要计算每个环的方案数,最后乘起来就可以。
- 问题可以转换成:$1,2,...,m$ 绕成一个环,有多少个选数方案使得每相邻两个位置至少被选了一个数。
- $m=1,2$ 时答案很显然,为 $1,3$。
- $m>2$ 时,假设我们从原来的环 $1,2,...,m-1$ 插入一个 $m$。
- 令环大小为 $m$ 的答案为 $f(m)$,那么有关系式 $f(m)=f(m-1)+f(m-2)$。
- 这个式子可以理解为 $1,2,...,m-1$ 的环插入元素 $m$,$m$ 选/不选得到的方案数和。读者可以自证一下。
Code:https://atcoder.jp/contests/abc247/submissions/30876626
G - Dream Team(Difficulty: 2159)
- 有 $N$ 个人,每个人有两个属性 $a_i,b_i$,以及他的价值 $c_i$。
- 现在要从这 $N$ 个人中选择 $k$ 个人,要求这 $k$ 个人两两的 $a_i$ 不相同,两两的 $b_i$ 也不相同。
- 请问 $k$ 的最大可能值 $k_0$ 是多少?对于 $k=1,2,...,k_0$,求出恰好选择 $k$ 人所能得到的最大价值和。
- $N \le 30000$,$a_i,b_i \le 150$。
Solution:
- 很容易想到网络流。既然要每个 $k$ 都算答案,我们如果每次在初始的图上限流,跑 $k$ 次 MCMF 时间复杂度就炸了。
- 这时我们应该联想到 EK 算法是单线程求网络流的,可以理解为如果流入边限制为 $1$,那么 EK 算法每增广一次,最大流最多增加 $1$。
- 然后就可以用这个性质,只需要跑一次 MCMF 即可。
- 虽然时间复杂度上界是 $\mathcal{O}(fnm)=150^4$ 的($f$ 是最大流,$n$ 是点数,$m=n^2$),但是卡不满,所以跑得非常快。