CF803 - EDU20

发布时间 2023-06-01 14:08:02作者: jucason_xu

A

最优化字典序问题一般考虑贪心。我们从左上往右下一路扫描,然后贪心的往里填,只要当前的 \(k\) 够就填一个。如果到最后 \(k\) 都没用完就说明不存在方案。

B

一个位置最近的 \(0\) 要么在左边要么在右边。考虑从左右各扫一次求出每个数到左边和右边最近的 \(0\) 的距离。然后取 \(\min\) 即可。

C

首先对于任何的序列,只要满足 \(n\ge \dfrac{k(k+1)}{2}\) 就可以构造出来。因为我们可以构造一个等差数列,然后把差的都补在最后一位。然后,如果 \(x\) 可行,那么把所有的数除以 \(x\) 就是对 \(n/x\)\(k\) 的答案。所以我们可以枚举 \(n\) 的所有因子,找到最大的满足条件的。然后构造一个 \(x\) 倍的等差数列,差的都填在最后一位。

D

考虑二分答案。首先 - 是等价的。我们可以先 getline 然后把所有的 - 替换成 ,之后用 stringstream 读入每个字符串的长度。然后二分每一层的宽度,贪心的往当前层塞更多东西。然后判断当前行数是否满足要求。

E

考虑 dp,设 \(dp_{i,j}\) 表示当前 dp 到第 \(i\) 位,目前 \(W\) 的个数比 \(L\)\(j\) 个是否可以达成。如果是 \(W,D,L\),直接转移,如果 \(?\),则同时使用 \(W,D,L\) 的转移,在除了最后一位的所有地方清除 \(dp_{i,-k}\)\(dp_{i,k}\),为了避免负数,我们把所有的 \(j\) 加上 \(k\)。然后回溯的时候可以不必记录回溯数组,而是直接在上一位找一个 \(dp_{i,j}=1\) 的位置进行转移。\(j\) 只能是当前的 \(j\) \(+1,+0,-1\)。复杂度 \(O(nk)\)

F

首先考虑 \(f_i\) 表示有公因子(非最大公因子)\(i\) 的子序列个数。然后我们要的 \(g_i\) 满足 \(f_i=\sum_{i|j}g_j\)。应用莫比乌斯反演的第二种形式,\(g_i=\sum_{i|j}f_j\mu(\dfrac{j}{i})\)。然后我们需要的是 \(\sum_{i\ge 2}g_i\),也就是 \(f_1-g_1\)。我们发现 \(f\) 可以用快速幂求出,\(g_1\) 可以 \(O(n\log n)\) 快速求。线性筛预处理 \(\mu\) 即可做到 \(O(n\log n)\)
或者每次枚举当前 \(i\) 的所有倍数,然后 \(g_j=f_i-\sum_{i|j,i\neq j} g_j\)。通过调和级数可证明运算的总次数是 \(O(n\log n)\)。这样我们可以计算出所有合法的 \(g_i\),也不需要莫比乌斯反演。

G

第一步,因为从 \(1\) 开始不太方便,我们把所有的下标减一处理。这样就可以直接取模确定当前位置对应 \(b\) 中哪个位置。把所有的询问/修改区间离散化,我们发现,我们可以在初始化的时候查找线段树每个叶子节点的最小值,然后合并。之后的查询每次都是一定覆盖整个叶子,所以只有初始值是特殊处理的,其他都和原问题一样:区间覆盖,区间最小值。考虑对叶子节点快速求出初始最小值,假设叶子节点对应 \([l,r]\),那么分三种情况:

  • 当前区间大小大于 \(n\),一定包含一个完整的 \(b\),答案为 \(b\) 中最小值。
  • 当前区间落在一个 \(b\) 中,为 \(b\)\([l\bmod n,r\bmod n]\) 区间最小值。
  • 当前区间横跨两个 \(b\),为 \([0,r\bmod n]\)\([l\bmod n,n-1]\) 的区间最小值的最小值。
    预处理 st 表,就可以 \(O(1)\) 查询。初始化之后后面的就简单了。复杂度 \(O((n+q)\log n)\)