AGC 做题合集 #4

书接上回,代码可以在 这里这里(仅包含 AGC024)查看。

  1. AGC009C Division into Two[1]
  2. AGC017D Game on Tree[2]
  3. AGC010C Cleaning[3]
  4. AGC016C +/- Rectangle[4]
  5. AGC008F Black Radius[5]
  6. AGC009D Uninity[6]
  7. AGC010D Decrementing[7]
  8. AGC024C Sequence Growing Easy[8]
  9. AGC024D Isomorphism Freak[9]
  10. AGC024E Sequence Growing Hard[10]

  1. AGC009C Division into Two

    给定 \(n\) 个不同的整数 \(\{s_i\}\),求将它们分成两个集合 \(X,Y\),并且 \(X\) 集合中任意两个数的差 \(\ge A\)\(Y\) 集合中任意两个数的差 \(\ge B\) 的方案数。

    $ 1 \le N \le 10^5 $。


    比较 easy 的一个 AGC 题!

    首先可以很轻松地列出状态,\(f(i)\) 表示仅考虑 \(1 \sim i\) 的元素,\(i\) 作为最后的 \(X\) 集合中最后一个元素的方案数。

    然后我们发现这个不太好统计关于的 \(Y\) 的限制,最难的限制应该是上一个元素左边的 \(Y\) 和右边的 \(Y\) 是否合法,这个难以记录状态,但是如果 \(A \ge B\) 呢?我们可以发现,对于当前位置 \(x\),我们枚举上一个位置为 \(lst\),如果 \(s_{lst +1} - s_{lst - 1} \ge B\),那么就一定是合法的!因为这个是最坏的情况了,对于其他情况,因为 \(A \ge B\),一定合法。

    接下来就是比较 easy 的限制了,考虑 \(x\)\(lst\) 中间的元素作为 \(Y\) 集合是否合法,于是我们可以考虑用队列维护所有合法的转移点,如果出现了两个元素放到 \(Y\) 集合中明显合法,那么一段前缀的转移点都要删除,然后转移的时候要满足两个点距离为 \(A\),这个可以 二分/指针 维护,这里我为了方便开了两个队列维护。 ↩︎

  2. AGC017D Game on Tree

    有一棵 \(N\) 个节点的树,节点标号为 \(1,2,⋯,N\),边用 \((x_i,y_i)\)表示。 Alice 和 Bob 在这棵树上玩一个游戏,Alice先手,两人轮流操作:

    选择一条树上存在的边,把它断开使树变成两个连通块。然后把不包含 \(1\) 号点的联通块删除

    当一个玩家不能操作时输,你需要算出:假如两人都按最优策略操作,谁将获胜。

    \(1 \leq N \leq 200000\)\(1\leq x_i,y_i \leq N\)


    首先可以猜测,这个和 SG 函数有关,于是我们要猜一个 SG 函数满足可以描述题目中的性质。

    对于树形结构,可以设 \(f(i)\) 表示以 \(i\) 为根的子树的 SG 函数,因为一个点对应的子树的博弈问题是所有子节点的问题的组合,于是 \(x\) 的 SG 函数是子节点的 \(\rm xor\) 和。

    初步结论就是 \(f(x) = \mathrm{xor}_{y \in son_x} f(y)\),然而这样没有考虑到 \(x\) 上面挂的边的影响,于是可以进一步猜测挂边就是令 \(f(x) + 1\),于是递推式就是:\(f(x) = \mathrm{xor}_{y \in son_x} f(y) + 1\)

    因为猜对了结论,于是不想证明了。 ↩︎

  3. AGC010C Cleaning

    一棵树,第 \(i\) 个节点上有 \(a_i\) 个石头,每次选择两个叶子节点(度数为 \(1\) 的节点),将路径上经过的(包括起点终点)所有节点上都取走一个石头,如果路径上有一个点上没石头这个操作就不能进行,问能不能取完所有石头。

    \(1 \le n \le 10^5, 0 \le a_i \le 10^9\)


    对于树形问题,首先要找到一个比较好的递归解决方式,通常可以从上而下或者从下而上,对于这个题,如果从上而下,那么意味着有很复杂的 DP 或者决策,于是优先考虑从下而上进行推导。

    于是我们的问题变为,对于一个以 \(x\) 为根的子树,它能否完全被消除(只考虑这个子树是否为 YES),如果不能,会怎么样?

    分为两种:

    • 少了路径消除 \(a_x\) 的部分,这个直接寄了。
    • 多了路径消除 \(a_x\) 部分,这个可以交给它的父亲进行消除。

    于是有了初步思路:记录 \(f_i\) 表示消除 \(i\) 为根的子树后,还剩下多少路径留给父亲。

    考虑 \(x\) 的决策,我们先将 \(x\) 的所有儿子的 \(f\) 全部加起来 \(=totf\),那么这些路径我们先假设不匹配,那么就会消除 \(x\) 上这么多的石头,如果 \(x\) 上面还有石头,那么就直接寄了,如果 \(x\) 上的石头个数变为负数,我们可以每次合并两条路径,使得 \(x\) 上面的石头 \(+1\),一直操作下去,最多可以操作 \(\min\{\frac{totf}{2}, totf - \max_y f_y\}\),具体是考虑最大的子树,只能让这个子树和别的子树匹配。注意最好不要直接模拟,不然很容易被一个大小为 \(4\) 的菊花,每条边长度为 \(2\) 的图卡掉。

    然后就可以求出剩余路径数目了。只要最后 \(1\) 的路径剩余为 \(0\) 即可。

    这个时候可能会有一点小疑问,\(f_i\) 真的不能变动了吗?我们发现,让 \(f_i\) 改变根本还是要拆散一条路径,但是这样会使一个合法的点欠费,于是这是不可能的。 ↩︎

  4. AGC016C +/- Rectangle

    给定整数 \(H,W,h,w\),你需要判断是否存在满足如下条件的矩阵,如果存在,则输出任意一种可能的方案

    • 矩阵是 \(H\)\(W\)
    • 矩阵的每个元素的权值在 \([-10^9,10^9]\) 之间
    • 矩阵的所有元素权值和为正
    • 任意大小为 \(h×w\) 的子矩阵的元素权值和为负

    比较简单的构造题。

    首先,如果 \(H \bmod h = 0 \wedge W \bmod w = 0\) 那么一定无解,因为我们可以通过将整个网格分成不交的矩形使得整体和 \(\le 0\)

    接下来假设 \(H \bmod h \neq 0\)

    只要我们可以构造出 \(W = 1, w = 1\) 的方案,然后复制一下,一定满足原来的限制。

    因为 \(H \bmod h \neq 0\),其实我们可以对于 \(i \bmod h\) 讨论一下,如果 \(i \bmod h = 0(i \in [0, H- 1])\),那么我们就直接来一个 \(\infty\) 放上面,其他的我们就放一个 \(\frac{\infty -\varepsilon }{h - 1}\),这样必定满足条件,具体实现时 \(\infty = Hh, \varepsilon = 1\) 即可。 ↩︎

  5. AGC008F Black Radius

    Snuke 君有一棵 \(n\) 个节点的全白的树,其中有一些节点他喜欢,有一些节点他不喜欢。他会选择一个他喜欢的节点 \(x\),然后选择一个距离 \(d\),然后将所有与 \(x\) 距离不超过 \(d\) 的节点都染成黑色,问最后有多少种可能的染色后状态。

    两个状态不同当且仅当存在一个节点,它在两个状态中不同色。

    \(1 \le n \le 2\times 10^5\)\(\rm subtask\):全部都是喜欢的。


    妙妙题!死活想不到怎么去重/kk。

    首先考虑全部都是喜欢的怎么做,记 \(S(x, d)\) 表示所有距离 \(x\) 小于等于 \(d\) 的点的集合,如果 \(S(x, d) = U\)(全集),我们直接令这个状态不合法。

    于是有第一个限制\(d<\)\(x\) 出发的最长路长度,超过这个会变成全集。

    接着考虑重复计算的部分,考虑两个点 \(x, y\) 以及两个距离 \(d_1, d_2\),如果 \(S(x, d_1) = S(y, d_2), d_1 > d_2\),那么我们提取出 \(x \to y\) 路径上面所有点 \(\{t_1, t_2, \dots, t_k\}\),那么有 \(S(t_j, d_1 - \mathrm{dis}(x, t_j))\) 也是和 \(S(x, d_1)\) 相同的,我们要钦定一个顺序,满足不会重复计算,于是我们可以钦定我们优先计算小的,也就是 \(S(y, d_2)\),容斥掉其他的元素,这样的好处就是对于一个 \(x\),合法的 \(d\) 一定是一段区间。

    现在,我们要求对于所有和 \(x\) 相邻的 \(k\)\(S(x, d) \neq S(k, d - 1)\),然后对于这个条件,首先 \(S(k, d - 1) \subseteq S(x, d)\) 的,而让两者相同,则意味着将整个树以 \(x\) 为根,所有距离 \(k\) 小于等于 \(d - 1\) 的点(也就是距离 \(x\) 小于等于 \(d - 2\) 的点,因为 \(k\) 子树里的不管了)就是整个树剔除 \(k\) 子树这个部分,求出从 \(x\) 除了 \(k\) 子树的最长路 \(t\),那么 \(d - 2 \ge t\) 的时候,\(d\) 就会不合法,即 \(d \le t + 1\)这是第二个限制

    于是我们可以求出每个点的 \(d\) 的上界 \(mx_i\)\(d \in [0, mx_i]\)


    考虑对于不喜欢的点的处理。

    首先喜欢的点还是随便选择 \(d\),但是不喜欢的点可能会因此容斥掉一些喜欢的点的方案,因此需要补上。

    对于一个点 \(x\),考虑所有和它相邻的点 \(k\),当 \(d\) 足够大的时候,就会将这个点的子树全部染黑(以 \(x\) 为根),如果这个子树里面有一个喜欢的点,那么这时候,这个方案就和从喜欢的点出发没有区别了,我们只要求出 \(t_i\) 表示所有和 \(x\) 相邻有喜欢点的子树中最长路的最小值,这个就是 \(d\) 的下界 \(mn_i\)

    以上所有变量都可以通过换根 DP 处理,于是答案就是 \(1+\sum_i (mx_i - mn_i + 1)\)↩︎

  6. AGC009D Uninity

    定义一个单独的节点为一棵 Uninity 0 的树。

    \(x(x \geq 0)\) 棵 Uninity k 的树全部连到一个节点上形成的树,称之为一棵 Uninity k+1 的树。

    显然,一棵 Uninity k 的树,同样也是一棵 Uninity k+1,k+2,k+3...的树。

    现在给你一棵树,求一个最小的 k 使得这棵树是一棵 Uninity k 的树。

    \(2 \le n \le 10^5\)


    首先,这个合并然后连上点的操作比较复杂,我们可以考虑给他一个等价的东西替代,我们可以给每个点一个标号 \(k_i\),同时满足任意两个 \(k_i\) 相同的点中间一定有比 \(k_i\) 更大的点,接下来我们只要最小化 \(k_i\) 即可。

    这个问题还是有点棘手,但是我们可以发现 \(k_i\) 一定是 \(\log n\) 级别的,于是 \(k_i\) 的出现情况可以用一个二进制数表示,接着我们可以考虑随便选择一个点作为根,顺着树形结构从下而上(先确定叶子的状态)进行 DP(这里仅仅是决策),对于一个点 \(x\),我们可以得到一个集合 \(S\) 表示所有还没有被其他东西阻挡的点构成的集合(也就是该点到 \(x\) 还没有一个比它大的点,我们称为关键点),我们可以先将所有 \(x\) 子树关键点合并起来,\(x\) 的权值一定是还没有出现的权值中一个,同时如果我们拿出这些关键点出现 \(2\) 次以上的元素构成的集合 \(T\)那么 \(x\) 的权值一定要 \(\ge \max\{T\}\)将两个条件结合,就可以找到 \(x\) 合法的选取方式,因为更小一定更优,于是找到最小的即可。 ↩︎

  7. AGC010D Decrementing

    题面

    黑板上写着 $ N $ 个整数。第 $ i $ 个整数是 $ A_i $ ,它们的最大公约数为 $ 1 $ 。

    高桥君和青木君将使用这些数来玩一个游戏。高桥君在这个游戏中是先手,他们将轮流进行以下操作(以下两步相当于一次操作):

    • 选择黑板中大于 \(1\) 的一个数,将其减 \(1\)
    • 此后,将黑板上所有数全部除以所有数的最大公约数。

    当黑板上的数全部为 \(1\) 时,不能再进行操作的人就失败了。两人都选择最好的方式行动,请求出哪边会最终胜利。

    \(1 \leq N \leq 10^5\)\(1 \leq A_i \leq 10^9\),从 \(A_1\)\(A_N\) 的所有数的最大公约数为 \(1\)


    题解

    比较神奇的博弈问题,只猜对了一半结论/kk。

    首先,如果整个序列形如 \(\underbrace{k, k, \dots, k}_{n - 1}, k + 1\),那么当前这个人一定必胜,但是这个还是不够,我们通过继续研究可以发现,\(k = 1\),因为上一个人如果料到他操作完了会变成这样,那么他一定令一个 \(k\) 变成 \(k - 1\)

    因此,必胜态就是 \(\underbrace{1, 1, \dots, 1}_{n - 1}, 2\) 的形式。

    首先,如果序列中出现了 \(1\),那么 \(\gcd\) 这个判断是没有任何用处了的,可以直接根据偶数的个数的奇偶性判断胜负(结论 1)。

    接着,我们可以暂且抛开繁琐的 \(\gcd\),考虑一个更简单的东西,即上面这个条件的变化量,如果目前有奇数个偶数,那么先手可以操作一个偶数,后手无论如何都会使得偶数奇偶性不变,同时无论如何都存活着一个奇数(假设之前有奇数,不然不可能),因此 \(\gcd\) 始终不会是 \(2\) 的倍数,只要先手不断坚持,一定可以到达必胜态,于是先手必胜(结论 2)。

    如果目前有偶数个偶数呢?这个不就是上面先手给后手留下的烂摊子吗?但是还有点不同,前面先手留的烂摊子保证了至少有 \(2\) 个奇数(操作前至少一个,后面改出了一个),\(\ge 2\) 个奇数的情况已经说明了,我们被安排得死死的,于是我们只要考虑只有一个奇数的情况,我们对这个奇数操作一下,然后就会触发除以 \(\gcd\) 的翻盘机制,只要递归判断即可(结论 3)。

    综上所述,直接讨论后递归求解即可,因为每次递归每个数会 \(/2\),于是复杂度为 \(\mathcal O(n\log V)\)

    启示

    • 对于复杂的操作,我们要学会分析特殊情况,并且从中找到便于刻画状态的变量,然后讨论决策。
    ↩︎
  8. AGC024C Sequence Growing Easy

    有两个长度为 \(n\) 的序列:\(a,x\)。现在给出 \(a\) ,并且已知 \(x\) 是空序列,请问至少做多少次下列操作才能使 \(x\) 变成 \(a\)

    \(x_i=x_{i-1}+1\)

    若无法变成,输出 \(-1\),若可以,输出最少的次数。


    简单题。

    假设 \(\{a_i\}\) 只有一个位置有数,为 \(x\),我们要得到 \(x\),就要操作 \(x\) 次,然后会生成一个 \(0,1,2, \dots, x\) 的数列,因为这个会影响前面的东西,于是我们倒着考虑生成 \(\{a_i\}\)

    为了方便,可以将序列划分为若干段,满足每一段只有且必须第一个数是 \(0\),其他的数不是 \(0\)(一个序列如果前导 \(0\) 多了也没有用,少了更不行,因为必须有一个不变)。

    接着倒着考虑生成,每次就是搞一个等差数列,同时讨论一下是否能利用之前的等差数列并不重新造一个,同时要注意如果等差数列起始点已经不是 \(0\) 了,要返回 \(-1\),次数简单计算即可。 ↩︎

  9. AGC024D Isomorphism Freak

    给定一棵点数为 \(n\) 的无根树。对于两个点 \(u,v\) , 若有以 \(u\) 为根与以 \(v\) 为根树同构,则染上同一种颜色。

    可以给这棵树加若干点, 问加完点后树最少能有多少种颜色, 以及在最少颜色的情况下最少有多少个叶子节点。

    \(n \le 100\)


    其实完全可以出到 \(5000\),ATC 真的擅长数据范围欺诈。VP 的时候看错了题面,居然打了一个树哈希,然后过不了样例,不然可以早点切的

    手玩样例可以直观感受到我们的最后的图是一个高度对称的图案,也只有这种图案才能使得染色数目最少。

    于是启发我们枚举对称中心(可能在边的中点上哦),接着 DFS,如果当前这个点 \(x\)\(k\) 个儿子,那么就要求最后生成的树每个深度和 \(x\) 相同的点的度数(不考虑父亲)都是 \(k\),这个可以简单取 \(\max\) 得到,这样构造也是最优的,最后的染色数就是最深的 \(dep\)。然后叶子数就是每个深度要求的度数之积即可。

    可能 \(100\) 纯粹为了防止炸掉范围。 ↩︎

  10. AGC024E Sequence Growing Hard

    题面

    给定 \(n\), \(k\), \(m\) , 问有多少个序列组 \((A_0,A_1,…,A_n)\) 满足:序列 \(A_i\) 的元素个数为 \(i\) ; 所有元素都在 \([1,k]\) 内; \(\forall i\in[0,n)\) , \(A_i\)\(A_{i+1}\) 的子序列且 \(A_i\) 的字典序小于 \(A_{i+1}\)

    输出在 \(\bmod~m\) 意义下的答案。

    \(n, k \le 300, m \le 10^9\)


    题解

    考虑怎么样插入是合法的,假设我们插入一个权值为 \(v\) 的数在 \(x\) 前面,首先要求是 \(v \ge x\),其次,如果 \(v=x\),那么无非是将 \(x\) 的所在连续段延长了 \(1\),会算重,因此 \(v=x\) 的情况可以直接不管。同时为了方便,我们在末尾加一个 \(0\)

    接着这个问题还是比较棘手,然后有一个神仙的思路:建树!

    我们建立一个 \(n+1\) 个节点的树,如果我们让 \(x\) 插在 \(v\) 前面,那么 \(x\) 就是 \(v\) 的儿子,同时,每个节点有两个权值 \(tim \in [0, n]\)\(val \in [1, k]\),每个儿子节点的 \(tim\)\(val\) 都要比父亲的大。于是可以记 \(f(x, i)\) 表示 \(x\) 个节点构成的树,其中根的 \(val\)\(i\) 额方案数,转移可以枚举最后一个子树大小以及权值,有 \(f(x, i) = \sum_{y = 1}^{x - 1} f(x - y, i)\binom{x - 2}{y - 1} \sum_{j = i + 1}^k f(y, j)\),中间的组合数是权值分配方案吗,后面的一个 \(\sum\) 可以前缀和优化解决,复杂度 \(\mathcal O(n^3)\)

    启示

    • 在排列中不断插入数的过程可以往建树上面靠。
    ↩︎
posted @ 2022-06-22 21:04  Werner_Yin  阅读(120)  评论(0编辑  收藏  举报