【补题】LongChallenge
2021
Dec. (div.2)(Unrated)
Increasing String
想到正解,但没实现出来。。。WA 了两发就心态爆炸了
官方题解 够详细了,简单写两句
先用单调栈求出不降序列作为初步不选的字符,记作 \(a\),选出的记作 \(b\),那么还要选的字符一定是 \(a\) 的后缀(可能为空)。
\(a\) 的后缀中大于 \(b[1]\) 的字符一定还要选;
等于 \(b[1]\) 的字符是否选取决于它与 \(b[p]\) 的大小关系(\(b[p]\) 为第一个不等于 \(b[1]\) 的字符),若大则选。
证明:\(a\) 后缀中 \(=b[1],>b[p]\) 的这部分选出后不论放在哪都是不劣的,因此直接选出来即可。
Nov (div.3)
Flip or Compress
以全变为 \(0\) 为例,考虑贪心。
一个 naive 的想法是对于 \(\ge2\) 的连续 \(1\) 进行 Compress+Flip(称为策略 \(1\)),很容易找到反例:11011
。
这种情况只需要三次操作:Flip \(0\),Compress,Flip(称为策略 \(2\)),不过只有这一种情况比策略 \(1\) 更优,分类讨论:
0100,0010100
:Flip00101100,001100
:策略 \(1\)11011,1101011
:策略 \(2\)
考虑实现:先扫一边,对左右都是 \(0\) 且左/右两位有 \(0\) 的 \(1\) Flip;然后对左右都是 \(1\) 的 \(0\) Flip;最后对每段使用策略 \(1\)
不过 std 的实现非常巧妙:从前往后扫,遇到与左有数字均不同的就 Flip,然后对每段使用策略 \(1\)。根据上面的分类讨论,这样恰好对每种情况都采取了最优策略。时间复杂度 \(O(|S|)\)
Functional Array
\(B\) 是 \(fA\) 前缀和的子序列,\(fA\) 是 \(Z\) 的子序列,有解等价于将 \(Z\) 分成 \(n\) 段,满足第 \(i\) 段中选出若干个数之和为 \(B_i\),显然每段的右端点越靠左越好。考虑 bitset
优化 \(01\) 背包,如果能拼出当前数就清空 bitset
,继续拼下一个
注意特判 \(fB_{i}<0,fB_{i}=0\) 的情况
\(O(\frac{n^{2}}{\omega})\) 能过 \(10^5\)
Oct (div.3)
Sep (Div.3)
Minimize Digit Sum
根号分治的新套路
- \(B\le\sqrt{n}\):暴力枚举 \(B\)
- \(B>\sqrt{n}\):\(n=aB+b\),不同的 \(a\) 只有 \(\sqrt{n}\) 种,\(a\) 相同时 \(B\) 越大 \(b\) 越小,枚举 \(a\) 即可
复杂度 \(O(\sqrt{n}\log n)\)