AGC 做题合集 #7
代码在 这里。
- AGC022D Shopping[1]
- AGC029C Lexicographic constraints[2]
- AGC017C Snuke and Spells[3]
- AGC029E Wandering TKHS[4]
- AGC029F Construction of a tree[5]
- AGC011D Half Reflector[6]
- AGC035D Add and Remove[7]
- AGC035C Skolem XOR Tree[8]
- AGC037D Sorting a Grid[9]
- AGC035F Two Histograms[10]
AGC022D Shopping
有 \(n\) 个商场, 第 \(i\) 个商场在数轴上的 \(x_i\) 处, 你需要在第 \(i\) 个商场花费连续的 \(t_i\) 单位时间购物。
现在有一趟火车会在 \(0\) 到 \(L\) 处往返, 行驶一单位距离要花费一单位时间。
你从 \(0\) 时刻起在 \(0\) 处上车, 只有在商场, \(0\) 处或 \(L\) 处才能下车, 问最少花费多少单位时间能在每一个商场都购完物后回到 \(0\) 处。
\(n\leqslant 3\times 10^5\),\(0<x<L\leqslant 10^9\)。
首先,为了方便后面讨论,我们对于 \(t_i \ge 2L\) 的点直接 \(ans \gets ans + (t_i \bmod 2L)2L,t_i\gets t_i \bmod 2L\),接下来假设 \(t_i < 2L\),我们可以发现答案一定是 \(2L\) 的若干倍。
答案上界一定是 \(2L(n+1)\),考虑构造:
从 \(i-1\) 到 \(i\),然后在 \(i\) 处下火车,接着停留 \(2L\) 的时间,火车一定回到了当初下车的状态,总共 \(n+1\) 次后回到起点。
定义 \(l_i\) 表示火车从左边经过 \(i\),然后开始购物,能否在火车下一次经过的时候上车,定义 \(r_i\) 表示火车从右边经过 \(i\),然后开始购物,能否在火车下一次经过的时候上车。
我们发现,对于 \(i < j, r_i = l_j = 1\) 的一个点对,我们可以在 \(i - 1\) 到 \(i\) 的时候先不停留,先到 \(j\),购物完后回到 \(i\) 再购物,可以发现这个只要一个 \(2L\) 就解决了两个点,于是我们要让 \(i <j, r_i = l_j = 1\) 的匹配尽可能多(但是要注意 \(n\) 是不能参与匹配的)。
将所有点分为 \(4\) 种:
- \(l = r = 0\),直接忽视,这个是必须付出 \(2L\) 的代价才能达成的。
- \(l = 1, r = 0\) 以及 \(l = 0, r = 1\),这种两点只能和 \(l = r = 1\) 进行匹配。
- \(l = r = 1\),这种点不仅可以和上面的两种匹配,还能同类型之间匹配。
同时我们可以发现,对于 \(l = 1, r = 0\) 的情况,有 \(2(L - x) \ge t, 2x < t, x \le \min\{\frac{t}{2}, L - \frac{t}{2} \}\),于是有 \(x \le \frac{L}{2}\),对于 \(l = 0, r = 1\) 有 \(x \ge \frac{L}{2}\),这两种点的范围是不交的。
于是可以分为其那面一部分和后面一部分进行贪心匹配(只能和 \(l = r = 1\) 匹配),然后剩下的 \(l = r = 1\) 两两匹配。 ↩︎
AGC029C Lexicographic constraints
给出一个大小为 \(n\) 的序列 \(\{A_i\}\),然后你要求一个最小的字符集满足你可以用这个字符集里面的元素构造出 \(n\) 个串,\(S_1, \dots, S_n\),满足 \(|S_i| = A_i\),求最小字符集大小(可以 \(> 26\))。
\(n \le 2\times 10^5, A_i \le 10^9\)。
简单题。首先二分一个答案 \(mid\),如果这个串比上一个串要长,就在后面无脑加 \(\tt a\),否则找到最后一个 \(\le A_i\) 且可以增大的位置然后将这个字符增大。
因为大部分都是 \(\tt a\),于是可以使用
set
维护不是 \(\tt a\) 的位置,至于找到可以增大的位置可以暴力向前找,最多找 \(\log V\) 次一定可以找到位置(或者无解)。 ↩︎AGC017C Snuke and Spells
\(N\) 个球排在一起,每个球上有一个数 \(a_i\)。接下来会进行若干轮删除。设现在还有 \(k\) 个球,则 \(a_i=k\) 的球会被删除。
最终可能球不会被删完,你需要求出最少修改几个球上的数后可以让球全部被删完。
同时还有 \(M\) 次修改,每次修改第 \(X_i\) 个球的数为 \(Y_i\),你需要求出每次修改后上述问题的答案。
\(1 \le N \le 200000\)。
感觉以前见过一个类似形状的省选题?但是不记得在哪里了,于是瞎猜了一个结论发现正确了。
这个题的 Difficulty 居然有 *3100?/qd
考虑给定一个序列如何判断最多不修改的球。
从大到小考虑,如果数字 \(x\) 的球有 \(i\) 个不修改,那么下次我们不修改的球的值最多是 \(x - i + 1\)。
不妨想象一个多米诺骨牌的状态,我们每次记数字为 \(x\) 的球保留 \(i\) 个,于是在 \(x\) 的位置上面有一个高度为 \(i\) 的柱子,那么我们就会推倒 \(x\) 这个柱子,所有 \([x - i + 1, x]\) 的位置都被堆满了多米诺骨牌。
进一步转化,我们推倒所有柱子后,都是不能相交的,于是每个位置最多防止 \(1\) 个元素。
暴力 \(\tt check\) 可以这么写,记数字 \(x\) 的球有 \(i\) 个,那么我们令 \(a[x - i + 1 \sim x] + 1\),答案就是 \(\sum_{i = 1}^n \min\{a_i ,0\}\)。
显然,就算带修也可以使用数组轻松维护。代码非常舒适。 ↩︎
AGC029E Wandering TKHS
高桥君的公司里有 \(n\) 个房间,形成一棵树的结构。某一次他在第 \(r\) 个房间里迷路了,他想回到第 \(1\) 个房间。为了回到 \(1\) 号房间,他会做以下操作:
- 设 \(S\) 是一些点的集合,一开始令 \(S=\{r\}\)。
- 他会选择 \(S\) 之外的,与 \(S\) 中的点相连的,编号最小的点 \(x\),然后把它加入 \(S\)。
- 若 \(1\in S\) 则停止操作,否则重复操作。
设 \(c_r=|S|-1\),要求 \(c_2,c_3,\dots,c_n\)。
\(n\le 2\times 10^5\)。
稳定发挥,连着干了 \(3\) 个 AT 的红题。虽然这个题有 *3000 的思维难度,但是不影响我们使用数据结构补足思维缺陷。相较于其他 AGC 的题,这个题代码略长。(自己瞎搞的做法)
因为是树,所以必须要有一个根,于是我们以 \(1\) 为根。
考虑每个点逐步拓展到达 \(1\) 的过程,我们要重点观察这个点到 \(1\) 的路径的拓展,记 \(t_1, t_2, \dots, t_k\) 表示这个点到 \(1\) 路径上面的点,其中 \(t_k = 1\)。
从 \(t_i \to t_{i + 1}\) 的过程中,我们会选择所有“在 \(t_i\) 子树里面,到达 \(t_i\) 的路径上最大值 \(\le \max_{j = i+ 1} ^ k\{t_{j}\}\) ”的所有点。
考虑简化上面的条件,这个是后面这个值是固定的,可以直接求出,对于每个 \(x\),我们维护它到根的权值 \(\max\) 和 次 \(\max\),如果 \(t_i \le \max_{j = i +1}^k \{t_j\}\),那么就是要求 \(\max\) 要小于这个值,否则就是次 \(\max\) 小于这个值。这个显然可以扫描线 + 树状数组求出符合条件的点。
最后要注意到我们从 \(x\) 跳到 \(x\) 的父亲的时候,会重复计算子树里面的一部分点,如果我们不仅仅要统计一个点子树符合条件的点,还要统计这个点所有儿子的子树里面符合条件的(便于减去重复部分)。
写完发现好像只要记忆化搜索即可。↩︎AGC029F Construction of a tree
给定 \(n-1\) 个点集 \(W_i\)(全集为 \(\{1,2,\ldots,n\}\)),从每个集合内选两个点连边,使得最后形成一棵树。输出方案。
\(n-1\) 条边按顺序对应这 \(n-1\) 个集合输出。
\(n \leq 10^5\),\(\sum |S| \leq 2 \times 10^5\)。
神仙题。
考虑有解的必要条件,对于任意一个集合 \(S \subseteq \{1, \dots, n - 1\}\),考虑 \(S\) 中所有点集涉及的点(即 \(\{x | x \in W_i \in S\}\)) 的个数至少是 \(|S| + 1\),如果不满足,怎么样都有环。
至于充分性,我们可以通过构造说明。
注意到上面的条件就是一个 Hall 定理的翻版,于是我们可以建立二分图,左边 \(n\) 个点,右边 \(n - 1\) 个点,表示点集,如果一个点 \(x\) 在第 \(y\) 个点集中间,那么就连一条 \((L_x, R_y)\) 的边,而上面的条件等价于这个二分图对于右边的点有完美匹配。
于是先整一个完美匹配出来,我们取出左边没有被匹配的点 \(p\),进行 \(\tt DFS(p)\),每次执行这个函数的时候,我们不断找到右侧没有遍历过的点 \(R_t\),取出 \(R_t\) 的匹配 \(L_v\),连接一条边 \((p, v)\),然后执行 \(\tt DFS(v)\)。
这个构造是显然有解的,考虑反证法,因为每次我们访问的左部点个数 = 右部点 + 1,如果某一次停止了,我们可以取出右边还没有被遍历的点集 \(S\),显然它和左边被遍历的点没有一条边,也就是它最多剩下的 \(|S|\) 个左部分点有连边,这个显然违反了之前的条件,于是不会出现这种条件。 ↩︎
AGC011D Half Reflector
有一种机器,你可以从它的左边或者右边丢一个球进去,它有两种状态 \(A,B\)。如果处在 \(A\) 状态,你从哪里丢进来的就会从哪里吐出去,然后立即变成 \(B\) 状态。如果处在 \(B\) 状态,你从哪边丢进去就会从另外一边吐出来,然后立即变成 \(A\) 状态。
现在把 \(N\) 台这样的机器放在一排,告诉你他们处在什么状态。然后从最左边放 \(K\) 次球,每当前面那个球出去之后就放第二个。问最后所有机器的状态分别是什么。
\(N \le 200000, K \le 10^9\)。
好爽啊,又干了一个红题,不过好像做了一天多时间(虽然大部分时间在改考试题),还 WA 了 inf 发。一个比较关键的性质,考虑一种基本的变化(之后用
A -> B
表示当前求离开了 A 机子,准备撞上 B 机子):x -> B A x A -> A x A <- B x B -> A
同时我们注意到对于一段
BBBBB
,经过之后就会变成AAAAA
。手玩一下:
BBBAAABAABBA * ** * **
丢了一个球进去后就是:
AABBBABBAABA * ** * ***
上面的示例中,我们将整个序列划分连续段,对于每个连续段,我们取出最后一个元素作为终止符(*),于是就有了第二行的图像。
观察图像变化:
* ** * ** * ** * ***
非常有意思!整个图像向左移动一格,并且补上了第 \(n\) 个位置的 * 号。
经过一些对于 Corner Case 的讨论后,我们可以写出 \(\mathcal O(NK)\) 暴力:
维护所有 * 的位置。
-
如果最开始是一个
A
:- 1 位置有 *:移除这个 *。
- 1 位置没有 *:在 1 位置加上 *。
- 操作过后,最开始就是
B
了。
-
最开始是
B
:- 集体向前移动 1 格。
- 加上 \(n\) 位置的 *。
- 如果 \(0\) 位置有 *,那么移除 \(0\) 位置的 *,同时最开始的字符不反转。否则最开始的字符反转。、
发现这些操作大部分涉及全局 \(-\),那么打个减法标记然后使用双端队列维护即可。于是变成了 \(\mathcal O(K)\)。
接着我们发现在经过若干次操作(\(\mathcal O(n)\) 级别,我写的是 \(5n\))后,操作会出现大小为 \(1\) 或 \(2\) 的循环节,于是直接 \(K \bmod 2\) 即可。
时间复杂度 \(\mathcal O(n)\)。 ↩︎
-
AGC035D Add and Remove
有一个由 \(N\) 张牌组成的牌堆,每一张牌上都写有一个非负整数。自顶部开始,第 \(i\) 张牌上的数字为 \(A_i\)。
Snuke 将重复以下操作,直至牌堆里只剩两张卡为止:
- 从牌堆里选择三张连续的卡。
- 把三张卡中位于中间位置的卡吃掉。
- 把剩余的两张卡上的数字加上被吃掉的卡的数字后按照原来的顺序放回牌堆。
请找出最后剩下的两张牌上所写的数字之和最小是多少。
\(N \le 18\)。
看到 \(N \le 18\),想到了什么?!是不是 \(\mathcal O(3^n)\)?!
于是就对着这个想了半天,最后突然就会了。直接删数,是很不好处理的,于是考虑倒着处理,同时一个点对于其他的点的影响也是不好描述的,于是我们可以考虑一个点对于答案的贡献。
开始的时候,\(1, n\) 两个点不能删,于是对于答案的贡献都是 \(1\),之后我们在剩下的点中选择一个最后删除的点,我们可以惊喜地发现它的贡献就是 \(1 + 1 = 2\)!接着我们可以得到结论:对于一个区间,这个区间左边一个点贡献是 \(pl\),右边一个点是 \(pr\),那么我们考虑这个区间最后删除的点,它的贡献就是 \(pl + pr\),然后将这个区间分成两个小部分。
于是可以设 DP 状态,\(f(l, r, pl, pr)\),表示对于 \([l, r]\) 这个区间的答案,然后记忆化搜索。
开始觉得是不优秀的,因为 \(pl, pr\) 的增长速度是斐波那契数列级别的,可以到达 \(3000\) 左右,于是状态数可能很大。
但是通过爆搜 \(N = 18\) 的状态,我们可以发现,整个状态数在 \(10^6\) 级别,可以接受。 ↩︎
AGC035C Skolem XOR Tree
给定一个正整数 \(N\)。
试判断,是否存在这样一棵节点数为 \(2N\) 的树,满足:
- \(\forall i \in [1,N]\),第 \(i\) 号节点和第 \(i+N\) 号节点的权值均为 \(i\)。
- 第 \(i\) 号节点到第 \(i+N\) 号节点路径上的点的点权异或和恰为 \(i\)。
若不存在这样的树,请输出一行
No
。否则先输出一行
Yes
,然后再输出 \(2N-1\) 行,每行两个正整数 \(u,v\) 描述树上的一条连接 \(u,v\) 的边。\(1 \leq N \leq 10^5\)。
又是瞎构造 WA 半天。猜一个结论,有解的充要条件就是 \(n \neq 2^k\)。
如果 \(n = 2^k\),那么显然对于 \(n\),是怎么都没有办法找到一个路径有 \(2^k\) 这一位的,于是寄了。
接着我们发现 \(n\) 为奇数的情况是比较好构造的,直接构造一个以 \(1\) 为根的菊花,然后把剩下的点两两分组,然后连起来,比如这样:
2 - 3 - 1 - 2 - 3 - 1 4 - 5 - 1 - 4 - 5 6 - 7 - 1 - 6 - 7
对于 \(n\) 为偶数,我们可以通过手玩发现一定存在一条路径满足 \(\rm xor\) 为 \(n\) 的,于是在之前的基础上找到这样的路径,然后新增 \(n\) 的即可(写完发现大家都是直接找到 \(n \to \mathrm{lowbit}(n) \to 1 \to (n - \mathrm{lowbit}(n) + 1) \to n\) 的 \qd)。 ↩︎
AGC037D Sorting a Grid
给定一个 \(n\times m\) 的矩阵 \(A\) ,保证 \(A\) 内的元素为 \(1\) 到 \(n\times m\) 的排列。
将 \(A\) 每一行的元素任意排列得到 \(B\)。
将 \(B\) 每一列的元素任意排列得到 \(C\)。
将 \(C\) 每一行的元素任意排列得到 \(D\)。
要求 \(D_{i,j}=(i-1)\times m+j\),请输出一组合法的 \(B, C\)。
\(1\leqslant n,m\leqslant 100\)。
倒着考虑,我们操作 \(2\) 之后要让每个数在它应当在的行上面,而操作 \(1\),就是,对于使得每一列所有的数来自的行互不相同。
这个和匹配有点类似,但是限制有点杂,于是我们可以考虑一列一列地确定匹配(我就是这里卡主了然后开了题解),每次二分图随便确定一个匹配,之后继续确定之后的匹配。
为什么正确呢?因为这个图的性质保证了一定存在匹配,假设还有 \(k\) 列没有确定,我们的二分图左部分点就是 \(n\) 行,右部点就是要跳到的 \(n\) 行,然后我们可以发现左部点和右部点的度数都是 \(k\),如果不存在这种匹配,根据 Hall 定理,一定是有一个 \(S\),对于它连向的点集 \(T\),有 \(|S| > |T|\),而边数是 \(k|S|\) 的,于是一定有一个 \(T\) 中的点度数 \(\ge k + 1\),矛盾。 ↩︎
AGC035F Two Histograms
现在你有一个 \(n\times m\) 的网格,你会按顺序进行做如下操作:
- 把所有格子中的数都赋为 \(0\) 。
- 对每一行选一个 \(k_i\) \((0\leq k_i\leq m)\) ,并把这一行最左边的 \(k_i\) 个格子 \(+1\) 。
- 对每一列选一个 \(l_i\) \((0\leq l_i\leq n)\) , 并把这一列最上面的 \(l_i\) 个格子 \(+1\) 。
经过这些操作后,你可以得到一个只包含 \(0\),\(1\) , \(2\) 的网格。请你求出,在所有可能的操作下,可以得到多少本质不同的网格。
两个网格被称为本质不同的,当且仅当存在至少一个位置,两个网格对应位置上的数不同。
输出答案对 \(998244353\) 取模的结果。
数据范围:\(n,m\leq 5\times 10^5\) 。
神仙双射题。
对于所有不存在 \((i, j)\) 满足 \(k_i = j + 1, l_j = i\) 的方案,我们记为 regular expression,那么所有 regular expression 和网格填法构成了一个双射,具体可以看官方题解。
不存在这个条件容易想到容斥。
于是可以枚举这种点的个数进行容斥,有:
\[\sum_{x} (-1)^x \binom{n}{x} \binom{m}{x} x! (n + 1)^{m - x} (m + 1)^{n - x} \]其中,\(\binom{n}{x} \binom{m}{x} x!\) 表示钦定的这些行和列,并且配对,而 \((n + 1)^{m - x} (m + 1)^{n - x}\) 表示剩下的随便。 ↩︎