补题日记
ARC229A
题面
对于由大写英文字母组成的字符串 S,定义 f(S) 为以下操作能够重复执行的最大次数:
- 将一个
ARC子串替换为CRA。
给定一个整数 X。求一个由大写英文字母组成,长度在 [1,100] 之间的字符串 S,满足 f(S)=X。
思路
ARC -> CRA 可以把中间的 R 去掉
这时就变成构造一个含A和C的字符串使得满足 \(i<j\),\(S_i='A',S_j='C'\) 的数量等于 X 。
现在题目转化为了构造逆序对。
考虑在C中插入A,起始25个C,每个A贡献为它后面C的数量。
CF2262A1
题面
定义
其中 \(S\) 是一个非负整数集合,\(x\) 是一个正整数。
给出一个数组 \(A\) , \(A \subseteq \{0,1,\ldots,n-1\}\) 。
构造一个集合 \(B\) , \(B \subseteq \{0,1,\ldots,n-1\}\) ,使得 \(a_k=f(B,k)\) 。
思路
因为mex是最小的未出现非负数,所以 \(B\) 中一定不能出现元素使得 \(b\div k=a_k\) 。
所以说 \([a_k*k,(a_k+1)*k-1]\) 区间内的值不能属于 \(B\) ,差分一下然后选上所有不属于这个区间的值就行。
CF2262A1
题面
和Easy一样,但求的是 \(B\) 的合法数。
pre
调和级数:$$H_n = 1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = \sum_{i=1}^{n} \frac{1}{i} \approx log(n)$$
计数dp中常定义dp[i]表示最后一个选i的方案数,\(\sum_{i=l}^{r}dp[i]\) 就表示 \([l,r]\) 区间内所有元素可选可不选,且至少选一个的总方案。
思路
对于一个 \(a_k\) 需要满足 \([0,k-1],[k,k*2-1],[k*2,k*3-1] \ldots [k*(a_k-1),k*a_k-1]\) 每个区间都至少有一个元素在 \(B\) 中。
可以记录一个L数组,L[i]表示右端点为i的区间所对应最大的左端点。
这样做是因为被包含的区间可以满足它外面包着的所有区间。
现在的区间数量小于n。
开始dp。
dp[i]表示选第i个元素的方案数。
转移的过程实际上是从上一个区间向当前区间转移。具体的,令上一个区间为[l1,r1],当前为[l2,r2],那么dp[l1,r1]的求和就代表[l1,r1]中至少选了一个,当前dp[r2]又代表r2要被选,所以此时两个区间都满足被至少选了一个元素。
更具体的,实现中可以用一个类似前缀和的东西优化这个求和过程,在算dp[r]的时候将dp[r]加入sum,而在当前区间的上一个区间不用被考虑时,我们移动左指针l1-1到当前区间的l2-1,保证sum正好记录[l1,r2-1]。
答案即sum。
ARC229B
题面
选择一个正整数 \(x_0\) 按照i=1,2,3...的顺序依次给 \(a_i\) 减去 x,每一次操作后 x 除以二向下取整。
判断是否有可能通过若干此类操作,使序列 A 的所有元素都变为 0;如果可以,求使所有元素变为 0 的最少操作次数。
思路
一下减整个数列不好做,先考虑两个相邻数。
若 \(a_i\) 减去 \(s\),则 \(a_{i-1}\) 减去 \(2*s + [0,1]\)。
一次操作 \(a_{i-1}\) 最多比 \(a_i\) 多减 1 ,k 次操作就可以最多多减 k。
答案为 \(max(a_{i-1}-2*a_i)\) 。
整体不好想的时候先想部分,思维题大胆猜结论
CF2259H
题面
有一个数列,其中 \(a_i\) 表示距离i最近的0与i的距离为 \(a_i\),-1表示任意数。
-1有两种状态,分别为0与其他数,求所有-1的取法方案数。
思路
首先先判有无合法序列,和easy一样用差分跑一下。
-1有三种状态:
- 必须取0
- 可以任意取
- 受到其他-1的限制
第三种状态只会出现在有一个正数 \(a_i\) 两边都是-1,这时两个-1受到对方限制。
前两种是好做的,关注第三种。
这样一对-1一定是关于他俩中间的那个正数最近的一对,也就是说一对-1中间不会有其他可取合法0。
这样就可以形成若干个-1链,链之间不相交。对于同一个链内,不能出现相邻的非零,也就是相邻-1间至少要取一个0。
dp一下就结束了。
P2055
题面
有n个人,m张床,可以建立一些对应关系,求人床匹配的对大对数。
思路
典典的二分图匹配,注意是人匹配床,所以是 人->床 的单向边。
注意到匹配过程是不断找增广路,有反悔过程,所以建图不需要想太多,构建好初始匹配关系就好。
P10292
题面
有一个数列 \(a_i\) ,构造一个数列 \(b_i\) ,过程中每次放置 \(a_j\) 至第i位时需花费 i-j 体力,总体力为k,求字典序最大的 \(b_i\) 序列,其中相邻数不能相等。
思路
很朴素的每次贪心找最大的 \(a_j\) 就是对的。
转换一下说法就是找 \([i,i+k]\) 中最大的 \(a\)。
可以用线段树维护这个过程。
有几个注意点:
- 过程中维护的是严格次大值,也就是满足次大值严格小于最大值。
- 线段树修改节点时需要把所有内容全覆盖掉,要不会保留。
- Merge的时候也需要全覆盖旧节点。

浙公网安备 33010602011771号