抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

比赛地址

A - Darker and Darker

题意

有一个 \(H\times W\) 的网格,每个格子有黑白两种颜色。初始颜色是给定的。

你需要不断执行以下操作,直到所有格子全黑(保证一开始有黑色格子):

  • 对于每个和黑色格子有公共边的白色格子,变成黑色。

求操作次数。

\(H,W\le 1000\)

题解

直接将所有黑色格子作为起点进行 BFS 即可。

时间复杂度 \(O(NM)\)

代码

B - LRUD Game

题意

有一个 \(H\times W\) 的网格,有一个棋子,一开始在 \((s_r,s_c)\)

A 和 B 玩游戏,执行 \(N\) 次操作。A 和 B 每人有一个长度为 \(N\) 的字符串,分别为 \(S,T\)。第 \(i\) 次操作如下:

  • 首先,A 进行游戏。A 可以选择将棋子按 \(S_i\) 的方向移动一格,或不移动;
  • 然后,B 进行游戏。B 可以选择将棋子按 \(T_i\) 的方向移动一格,或不移动。

A 的目标是在某一次操作将棋子走出棋盘,B 的目标则相反。

判断两个人采取最优策略时棋子是否会在某一次操作走出棋盘。

\(H,W,N\le 2\times 10^5\)

题解

倒着考虑,维护不能走出棋盘的所有起点,可以发现这些起点一定是棋盘的一个子矩形。

倒着考虑时,每次 B 进行游戏会使该矩形的某一边界向外移动,而 A 进行游戏会使该矩形的某一边界向内移动。

注意矩形边界不能移出棋盘,并且若中途矩形变空,那么就再也不能向外移动了。

时间复杂度 \(O(N)\)

代码

C - Removing Coins

题意

给定一个 \(N\) 个点的树,每个点上有一个棋子。

A 和 B 轮流进行以下操作,A 先手:

  • 选定一个有棋子的节点 \(v\),取走 \(v\) 上的所有棋子;
  • 将剩余的所有棋子向靠近 \(v\) 的方向移动一条边。

不能操作的人输。

求两人采取最优策略时的胜者。

\(N\le 2\times 10^5\)

题解

注意到操作相当于选择一个节点作为根,然后将叶子结点删去。

考虑对于一次操作,若选择的不是度为 \(1\) 的点,那么直径会减小 \(2\);否则直径要么减 \(1\),要么减 \(2\)

于是我们只要在状态里记录直径上的点数即可。

时间复杂度 \(O(N)\)

代码

D - Complexity

题意

定义一个黑白网格的 complexity 为:

  • 若网格全黑或全白,则为 \(0\)
  • 否则,我们用一条水平的直线或竖直的直线将网格分成两个子网格,令两个子网格的 complexity 分别为 \(c_1,c_2\),则原网格的 complexity 为 \(\max(c_1,c_2)+1\) 的最小值。

给定一个 \(H\times W\) 的网格,求该网格的 complexity。

\(H,W\le 185\)

题解

考虑有两个简单的性质:

  • 一个 \(H\times W\) 的网格的 complexity 不超过 \(\lceil\log_2 H\rceil+\lceil\log_2 W\rceil\)
  • 一个网格在最后加入一行或最右边加入一列,complexity 不小于原网格的 complexity.

于是我们设计状态 \(f_{c,i,j,k}\) 表示操作次数为 \(c\),左上角为 \((i,j)\),下边界为 \(k\) 时,右边界的最大值。\(g_{c,i,j,k}\) 同理表示操作次数为 \(c\),左上角为 \((i,j)\),右边界为 \(k\) 时,下边界的最大值。

根据第二个性质,我们可以直接用双指针优化转移。

时间复杂度 \(O(HW(H+W)\log HW)\)

代码

E - Go around a Circle

题意

有一个 \(N\) 个点的环,点编号 \(1\)\(N\)。给定一个长度为 \(M\) 的只包含 RB 的字符串 \(S\),你需要给环上每条边填上 RB,使得对于任意 \(1\le i\le N\)

  • 假设初始有一个棋子在第 \(i\) 个点。你可以执行 \(M\) 次操作,每次沿一条边将棋子走到一个相邻的点。你需要满足存在一种操作方案使得第 \(j\) 条经过的边上的字符等于 \(S_j\)

求方案数。对 \(10^9+7\) 取模。

\(N\le 2\times 10^5\)

题解

不妨假设 \(S\) 的第一个字符为 R。显然环上不能有连续两个 B 出现。

那么我们考虑根据 B 将环分成若干个 R 的连续段。若 \(S\) 中的字符不全是 R,那么一定有每个 R 的极长连续段长度一定是奇数。这个可以用反证法证明。

另外,显然每段连续段还会有一个长度的限制。

这样我们就可以每次去掉开头的一段 RR..RRBB..BB,转化成一个类似的子问题。

注意「类似」是因为这个子问题的起点一定是每段 R 的两个端点,所以若该子问题开头的 R 的长度是偶数,该段 R 的长度并不会对环上每段 R 连续段的长度产生限制。

可以发现环上 R 的连续段只需要满足奇数和每个子问题产生的长度限制,就一定满足原问题中的限制。

于是直接 DP 即可。注意由于是环,可以把分界点取在最后一段的任意位置,所以最后统计答案时需要乘上最后一段的长度。显然这样做不会算重。

代码

F - Adding Edges

题意

给定一个 \(N\) 个点的树 \(T\)\(N\) 个点 \(M\) 条边的图 \(G\),你需要不断执行以下操作:

  • 选择三个点 \(a,b,c\) 满足 \(G\) 中存在边 \((a,b),(b,c)\) 但不存在边 \((a,c)\),若 \(T\) 中存在一条同时包含 \(a,b,c\)(任意顺序)的简单路径,则在 \(G\) 中加入边 \((a,c)\)

求最终 \(G\) 的边数。可以证明最终的 \(G\) 唯一。

\(N,M\le 2000\)

题解

若题目中的条件为 \(a,b,c\) 必须按该顺序排列,设原图为 \(G_0\),那么 \((x,y)\in G\) 当且仅当存在序列 \(x=v_1,v_2,v_3,\ldots,v_k=y\),满足 \((v_i,v_{i+1})\in G_0\)\(v_1,v_2,\ldots,v_k\) 按顺序被包含在树上的某条简单路径上。证明较为简单,不再展开。

现在的问题是原题目中 \(a,b,c\) 可以按任意顺序排列。考虑对于三个点 \(a,b,c\),若这三个点在树上按该顺序被包含在同一条简单路径上,且 \((a,b),(a,c)\in G_0\),那么我们可以把 \((a,c)\) 删去,加入 \((b,c)\) 而不影响答案。我们把这样的操作称为压缩。

若我们不断对原图进行压缩,直到不能被压缩,那么可以证明最终的图一定满足以上 \(a,b,c\) 必须按顺序排列时的性质。

那么问题是如何压缩。考虑依次加入边,我们记录 \(top(a,b)\) 表示 \(T\)\(a\) 为根时,\(b\) 的祖先中离 \(b\) 最近且在由当前 \(G_0\) 生成的最终的 \(G\) 中与 \(a\) 有边的点。

假设当前加入边 \((a,b)\),若有 \(top(a,b)=b\),那么无需再加入。若 \(top(a,b)\) 存在,则我们可以转化成加入边 \((top(a,b),b)\)

否则,我们加入边 \((a,b)\),更新 \(top(a,b)\)。然后我们需要 DFS 更新以 \(a\) 为根时 \(b\) 子树内点 \(v\)\(top(a,v)\) 值。

假设当前更新到了点 \(v\),若 \(top(a,v)\) 存在,由于是从上往下更新的,一定有 \(top(a,v)=v\)。此时我们需要将 \((a,v)\) 压缩,即我们需要再更新完后递归调用加边操作加入边 \((b,v)\)。这种情况下我们不需要再更新子树的 \(top\) 值,可以直接退出。

否则,我们将 \(top(a,v)\) 更新为 \(b\),继续更新子树。

压缩完后,我们只要从每个点开始 DFS 统计以这个点为边的一个端点的边的数量即可。

我们每次更新时,若 \(top\) 值不存在,我们会更新并继续递归;若存在则会压缩边。\(top\) 值一共只有 \(N^2\) 条,而边一共只有 \(M\) 条,每条最多被缩 \(N\) 次,所以时间复杂度为 \(O(N^2+NM)\)

代码

评论