个人感觉 A<B<C<D<E<G<F。
A - What month is it?
求 \(X\) 月的 \(Y\) 个月后是几月。\(1≤x,y≤12\)。
签到。
直接 \((X+Y)\mod 12\) 就行了,注意特判一下 \(X+Y≡0\pmod {12}\) 就行了。
当然这种做法太低级了,我们还有更先进的做法。
我们让 \((X+Y-1)\mod 12\) 就可以得到每个正确答案减一的结果,那我们直接加一就可以避免 \(X+Y≡0\pmod {12}\) 的情况。
同时 \(X,Y\) 都不小于 \(1\),所以不用担心 \(X+Y=0\) 的情况。当然世界上也没有零月这个月份,这是完全不需要考虑的情况。
C++通过代码。
B - Most Minority
有 \(N\) 个编号为 \(1\) ~ \(N\) 的人(\(N\) 是奇数),投 \(M\) 次票,每次选 \(0\) 或 \(1\)。每次投票后按规则加分:若所有人都选 \(0\) 或都选 \(1\),所有人各得 \(1\) 分;若有人既选 \(0\) 也有人选 \(1\),仅投少数派(选 \(0\) 或 \(1\) 的人更少)的人得 \(1\) 分。统计每个人 \(M\) 次投票的总得分,找出所有得分最高的人,按编号从小到大输出。
这次 B 题不难但有点超标,讲一下我的思路。
首先读入后统计第 \(i\) 次投 \(0\) 和投 \(1\) 的人数,我们记为 \(c_0\) 和 \(c_1\)。
- 如果 \(c_0=0\) 或者 \(c_1=0\) 则意味着所有人都选 \(0\) 或都选 \(1\),我们使用一个 \(s_i\) 记录编号为 \(i\) 的人的得分数,即 \(s_{1,...,N}\) 都加一。
- 如果 \(c_0<c_1\),则将投 \(0\) 的人得分加一;反之,将投 \(1\) 的人得分加一。
考虑 \(c_0=c_1\),注意到 \(N\) 为奇数,所以不存在这种情况。
统计完 \(M\) 次投票后,找到其中的最大得分,再按从小到大遍历一边 \(s\),输出所有最大得分编号即可。
C++通过代码。
这里的代码输出略有繁琐,使用了一个 vector
维护,但没有什么必要。
因为 Atcoder 非比赛期间不太方便提交,所以就不重交了。
C - Sum of Min Query
给定两个长度为 \(N\) 的整数序列 \(A\) 和 \(B\)。需要处理 \(Q\) 个查询。每个查询给出一个字符 \(c_i\) 和两个整数 \(X_i,V_i\)。如果 \(c_i\) 是 A
,则将 \(A_{X_i}\) 修改为 \(V_i\);如果 \(c_i\) 是 B
,则将 \(B_{X_i}\) 修改为 \(V_i\)。每次修改后计算并输出 \(\sum_{k=1}^{N} \min(A_k, B_k)\)。\(1≤N,Q≤2×10^5\),\(1≤A_i,B_i,V_i≤10^9\),\(1≤X_i≤N\)。
C 题犯了个下标错误导致被罚了 10 min。
C 题不难,但朴素暴力会达到 \(O(Q\times N)\),这显然不行。我们只需要一点思维就可以优化至 \(O(N+Q)\)。
我们先初始化一个 \(min\) 使 \(min=\sum_{k=1}^{N} \min(A_k, B_k)\)。那么对于每次修改,我们只需要先将 \(min\) 减 \(\min(A_x,B_x)\),再根据 \(c\) 修改 \(A_x\) 或 \(B_x\) 的值,最后再让 \(min\) 增加 \(\min(A_x,B_x)\) 即可。
C++通过代码。
D - Toggle Maze
有一个 \(H\) 行 \(W\) 列的网格,每个格子可能是空格(.
)、障碍物(#
)、起点(S
)、终点(G
)、开着的门(o
)、关着的门(x
)或开关(?
)。高桥从起点出发,每次能上下左右移到相邻格子,但不能移到障碍物或关着的门。特别地,每踩一次开关,所有门的状态会反转。请判断高桥能否走到终点,能的话求最少移动次数,不能则输出 \(-1\)。\(1≤H,W≤500\)。
这题一眼就是 BFS。看不出来就多练。
用 dist[state][i][j]
表示在门反转状态为 state 时到达 \((i,j)\) 的最小步数(state=0
表示初始状态,state=1
表示反转后状态)。初始化为 INT_MAX
。
从起点开始 BFS,初始状态为 \(0\)。
对每个位置,尝试向四个方向移动,计算新位置 \((ni, nj)\) 和新状态 \(n\)。若新位置是开关,则状态反转;否则状态不变。
判断移动是否合法,若合法且找到更短路径,则更新距离并加入队列。一旦到达终点,立即输出步数并结束程序。如果 BFS 结束仍未到达终点,则输出 \(-1\),表示无法到达。
时间复杂度为 \(O(H\times W)\),可以通过。
C++通过代码。
E - Reachability Query
给定一个包含 \(N(1 \leq N \leq 2 \times 10^5)\) 个顶点、\(0\) 条边的无向图。顶点编号为 \(1,2,\dots,N\),初始时所有顶点均为白色。
请处理总计 \(Q(1 \leq Q \leq 6 \times 10^5)\) 个以下 \(3\) 种类型的查询:
- 添加一条连接顶点 \(u\) 和 \(v\) 的无向边。\((1 \leq u < v \leq N)\),在该查询之前,未添加过连接 \(u\) 和 \(v\) 的边。
- 将顶点 \(v( 1 \leq v \leq N )\) 的颜色反转。
- 判断从顶点 \(v( 1 \leq v \leq N )\) 出发,经过 \(0\) 条或多条边后能否到达某个黑色顶点。若能到达,输出
Yes
;若不能到达,输出No
。
不是特别裸的并查集。也是挂了一发。
先分析一下。首先操作 1 就是合并两个以 \(u,v\) 为顶点的集合;操作 2 其实是找到顶点 \(v\) 所在连通分量的根节点,反转 \(v\) 的颜色时同步更新连通分量的黑色顶点数量和该分量是否有黑色顶点;操作 3 本质上是检查顶点 \(v\) 所在连通分量是否存在黑色顶点。
知道这些之后这题就很裸了,直接套个模板就完事了。
C++通过代码。
这里的代码用了按秩合并和路径压缩,整体时间复杂度为 \(O(Q\times α(N))\)。如果不太会并查集的可移步 我的随笔。
F - kirinuki
F 笛卡尔树不会,赛时读完题就跑了。
既然我不会就不给形象化题面了。
G - sqrt(n²+n+X)
给定整数 \(X(-10^{14} \leq X \leq 10^{14})\)。请求出所有满足 \(\sqrt{n^2 + n + X}\) 为整数的整数 \(n\)。
数学题。也是我 ABC 过的第一个 G。
令 \(m=\sqrt{n^2 + n + X}\),即 \(m^2=n^2 + n + X\),同时乘 \(4\) 可得 \(4m^2=4n^2 + 4n + 4X\),即 \(4m^2=(2n+1)^2-1+4X\),也就是 \(4m^2-(2n+1)^2=4X-1\),展开后可得\((4m+2n+1)(4m-2n-1)=4X-1\)。再令 \(d=4X-1\),则问题转化为找到整数对 \((a,b)\) 使得 \(a×b=d\) 且 \(b−a≡2 \pmod4\)。
接下来就很清晰了。我们计算 \(d\) 的绝对值的所有因子,对于每个因子 \(p\),考虑 \(a=p\) 和 \(a=-p\) 两种情况,计算对应的 \(b=d÷a\)。对于每个因子对 \((a,b)\),判断\((b−a)\mod4\) 是否等于 \(2\),若满足条件,则将 \((b-a-2)\) 的值加入集合。
最后输出集合即可。
C++通过代码。