1010 Sort
我们可以用调整法构造出唯一的贪心方案。
如果存在一种选择方案,那么将 b1 调整为 a1 中最小的元素,一定仍然合法;将 b2 选择 a2 中最小的、大于 b1 的元素,一定仍然合法,并且不会比原来的 b2 更大。
以此类推,我们可以构造出唯一的序列。
形式化地,对于任意一组 b1,b2,…,bn,我们可以定义序列 g1,g2,…,gn,满足:
- g1=min1≤j≤ma1j。
- gi=min{aij∣1≤j≤m,gi−1<aij},i≥2。
我们可以证明 ∀i,gi≤bi:
- 对 i=1,显然成立;
- 若 i−1 成立,则 i 时,既然 bi>bi−1≥gi−1,那么 bi>gi−1,于是 bi 也在 gi 的候选元素中,所以 gi≤bi。
因此只要存在一个解,那么贪心解就一定存在;反之,贪心解本身就是一个可行解。
此外,由于每一步都选择当前行中满足条件的最小元素,所以该序列是唯一确定的。
复杂度 O(nm)。
1007 Turn of a Page
如果存在一个 ai>S,那么包含这个元素的部分和一定大于 S,不可能等于 S。
如果存在一个 0<ai<S,那么无论如何排列,一定存在第一个满足条件的 ap;由于这样的元素前面只有 0 或 S,所以一定不存在 1≤q≤p,使得 ∑i=qpai=S。
所以现在可以将元素限制为 0 和 S 两种。如果 S 出现了,那么只要将序列排列成 S,S,…,S,0,0,…,0 即可;如果 S 没出现,自然不存在这样的重排。
复杂度 O(n)。
1008 谁输谁洗碗
直接暴力标记非法数字即可,复杂度 O(nk),其中 k=104,是可以过的。
其实本地造一个极限数据需要跑大概 10 秒,我个人认为如果是正式赛,这种题目应当适当放小数据范围。
1004 左右脑互搏
观察到 n 作为指数是可以接受的,所以可以对局面进行状压 DP。
具体地讲,对于 ∅ 状态,是输态;预处理出 Sl 表示 popcnt(x)=l 的所有 x,然后枚举 l=1∼n,所有 S∈Sl 都可以从 S∖{x}(x∈S) 并且满足异或和要求的集合转移过来,如果存在一个满足条件的集合是输态,那么当前就是赢态,否则是输态。
复杂度 O(n2n)。
1001 布布吃地瓜
我们先从简单的情况入手。
检查 0 是否能够成为答案,可以发现,如果存在一条不经过 0 的 (1,1)→(n,m) 的四连通路径,那么 0 是答案;
否则,如果存在每一条不经过 1 的 (1,1)→(n,m) 的四连通路径,那么 1 是答案;以此类推。
然后我们有一个 O((nm)2) 的做法:
- 从 x=0 开始枚举答案,每一次删掉所有 aij=x 的 (i,j),使用 BFS 检查 (1,1)→(n,m) 是否是四连通的。
考虑如何进行优化。设 Bx={(i,j)∣aij=x},那么 ∑x∣Bx∣=nm。
如果能够用上这个条件,即让复杂度为 O(∑x∣Bx∣)=O(nm),那么复杂度就是正确的。
这启示我们在每一轮循环只考虑 aij=x 的那些位置。
通过感性观察可以发现,下面这两件事是等价的,严谨证明需要依靠拓扑学知识,这里不做展开:
- 存在一条 (1,1)→(n,m) 的四连通路径,且路径上不经过任何 Bx 中的格子;
- 在 Bx 中,不存在一个八连通分量同时接触
我们可以用 BFS 判断,复杂度是 O(nm)。
1005 列车停放站
对于这种覆盖的问题,通常是需要通过贪心和考虑类似“第一个位置”这样的思路去做的。
对于每个询问 (x,y),考虑 i=argmaxj{lj∣rj≤y}。
如果 li<x 或者 argmax 的集合是空的,说明没有合法答案,答案就是 0。
否则答案至少是 1,那么假设最优解选择了 i1,i2,…,ik,由于最优解选择的区间都是合法的,那么有 rik≤y;根据 i 的定义,我们可以知道 li≥lik,于是调整 ik 为 i 后仍然是一个最优解。如果有多个满足条件的 i,那么对于每一个满足条件的 i,交换论证都成立,因此任选即可。虽然 i 不一定唯一,但是 li 一定是唯一的。
设 f(x,y) 是询问 (x,y) 的答案,那么 f(x,y)={0li<xor{j∣rj≤y}=∅1+f(x,li)otherwise。
于是我们可以离散化后预处理,然后对每一个询问倍增,这样复杂度是 O((n+m)logn)。
1006 游戏
其实这个题目并不是很难,但是看上去比较吓人,所以过的人不多。
重要的观察只是:如果某一个属性对最终答案能够产生贡献,那么它一定要 ≥40。
将每一个属性分开来看,设属性 i 最多能达到的值为 si,将 si 降序排序,由于 ∑si≤150,并且 si≥0,那么可以反证法证明 s4<40,即只有 s1,s2,s3 有可能产生贡献。
于是背包 DP 即可,复杂度 O(mk3)。
1009 GCD
对于每一个 i,令 gj=gcd(bj,bj+1,…,bi),根据 gcd 的结合律,有 gj=gcd(bj,gj+1)(j<i),又根据 gcd 性质有 gj≤gj+1。
当 gj<gj+1 时,这等价于 gjgj+1>1,又因为 gj∣gj+1,于是 gj≤21gj+1。又因为 gj≥1,所以从 gi=bi 开始,到 g1 为止,至多只有 O(logV) 个不同的值,其中 V=109,代表值域。
根据这个思想,我们可以对每一个前缀 [1,i] 预处理出它的后缀等值区间,具体地讲,用 vector 存每一个前缀对应的 O(logV) 个区间,更新的时候,可以从 i−1 继承而来,然后给每一块的 g←(g,ai) 并且再次双指针合并,这样预处理是 O(nlog2V) 的,其中有一个 O(logV) 是求 gcd 的复杂度。
对于这 O(logV) 个区间 [L,R] 来说,我们有这样的一个贪心的调整论证法:如果最优解存在一个不在 L 处的操作,我们可以把它取消掉,并且让这个操作在 L 处进行,那么操作仍然是合法的。根据这样的思路,每一段的操作都可以在区间的左端点处进行。
对于第一个区间 [L1,R1],容易看出 L1 处的操作数 t1≥⌈gL1maxL1≤j≤R1aj⌉。
如果 t1>⌈gL1maxL1≤j≤R1aj⌉,我们可以把多出来的操作都放到 L2 处,由于 gL2>gL1,所以操作仍然合法,那么我们就可以断定 t1=⌈gL1maxL1≤j≤R1aj⌉。
对于后续的段,我们可以记录一下前面累积减去了多少,然后最大值用 ST 表查,于是单次询问复杂度 O(logV)。
upd: 同样的前缀思路也被用在了 CCPC Final 2025 L 题。
1002 1003 通行证
把二进制数看成集合,设询问的集合是 x,那么对于每一个位置 (i,j),它的答案为 k 的充要条件是,在这个十字框中,所有距离 ≤k−1 的 (i,j) 都满足 aij⊆x;距离 =k 的 (i,j) 中存在一个 aij⊆x。
简单讨论可以发现这这等价于 ⋃dij≤k−1aij⊆x 并且 ⋃dij≤kaij⊆x。
对于一个给定的查询 x,我们可以形式化地写出答案:
Q(x)=i=1∑nj=1∑nk=1∑∞dij≤k⋃aij⊆x
反过来看,可以枚举每一个格子 (i,j) 对哪些 x 产生了贡献,这就导出了一个 O(n3) 的做法:
- 枚举每一个格子 (i,j),再枚举距离 k,给所有的满足 ⋃dij≤kaij⊆x 的 x 的答案 +1。
考虑进一步优化。对于每一个位置 (i,j),设 V 是值域,其二进制位最多改变 O(logV) 次,这就导出了一个 O(n2logV) 的优化:
- 用 DP 求出上下左右每一个位置第一次变化的位置,最后把这些位置取出来排序,给相同的 ⋃dij≤kaij 统一操作即可。
关于给所有超集 +1 的操作,这可以用 SOS DP 以 O(VlogV) 的复杂度解决。