【补题】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:Flip
  • 00101100,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)\)

posted @ 2021-10-13 08:19  401rk8  阅读(57)  评论(0编辑  收藏  举报