seerc2021

A

比较字符串的字典序可以进行贪心,所以用一个指针从前往后扫描,维护一个计数器,对于当前字符,如果两个串相同则可以累加计数器,否则若字典序较小,则统计答案,合法的区间左端点个数为计数器累加的数,右端点个数为右边剩下的数,若字典序较大,则清空计数器,因为以后的都不满足题意。

B

不难发现加的操作可以直接使用可持久化线段树维护,对于区间覆盖来说不太好弄,因为区间覆盖后无法很好的维护列,考虑列实际上很少,以及可持久化线段树具有很好的合并功能,所以对于每种可能的合并情况都使用线段树进行维护,如果区间覆盖就直接在没有这一列的情况下加入即可。

C

容易想到一个看上去时间复杂度很假的做法,枚举颜色,然后做树上背包,实际上用到一个结论,在树上归并时,如果限制子树大小为 kk,那么最终的时间复杂度是 O(nk)O(nk),这样的话最后时间复杂度为 O(n2)O(n^2)

下面证明这个结论,有两种方法理解。

方法一,考虑将两个联通块归并时,这两个连通块的大小,第一种,都大于 kk,那么归并一次的时间复杂度是 O(k2)O(k^2),归并次数不超过 O(nk)O(\frac{n}{k}),第二种,仅有一个大于 kk,那么每归并一次就会少一个小于 kk 的连通块,这样也是 nknk,第三种,都小于 kk,这样可以先合并出若干个大于 kk 的联通块,每个连通块消耗 k2k^2 ,最多 nk\frac{n}{k} 个块。

方法二,归并时强行假设枚举的点对是 dfn 序最接近的 2k2k 个点,这样点对中两个点的 dfn 序差不超过 2k2k,最后得到的点对是 nknk 级别的。

E

首先 BB 数组的顺序是不影响最终结果的,于是先将 BB 数组排序方便处理,不难发现我只需要知道前一个数是多少就能够对当前数进行决策,而前一个数最多只有 m+1m+1 种情况,得到一个 N2N^2 的算法,定义 dp[i][j]dp[i][j] 表示当前考虑到第 ii 个位置,这个位置上放 bjb_j 的最小步数,若 jj00,则表示不替换,转移只有如下几种情况,当 ai>ai1a_i>a_{i-1} 时,dp[i][0]=min(dp[i][0],dp[i1][0])dp[i][0]=min(dp[i][0],dp[i-1][0]),当 $a_i<a_{i-1} $时,对于所有满足 bj>ai1b_j>a_{i-1}dp[i][j]=min(dp[i][j],dp[i1][0]+1)dp[i][j]=min(dp[i][j],dp[i-1][0]+1),对于所有情况,dp[i][0]dp[i][0] 和所有比它小的 bjb_jdp[i1][j]dp[i-1][j] 的最小值,对于 dp[i][j]dp[i][j] 的更新,采用贪心策略,dp[i][j]=min(dp[i][j],dp[i1][j1]+1)dp[i][j]=min(dp[i][j],dp[i-1][j-1]+1),这样做是因为如果当前放 bjb_j ,那么前面放 bj1b_{j-1} 一定不劣,这样做是 N2N^2 的,考虑优化,发现可以将不替换的单独拿出来考虑,这个时间复杂度可以接受,只需要考虑替换时怎么维护 dpdp 值,发现需要做的只有将整个数组平移一个单位和区间对一个数取 minmin ,使用吉司机线段树维护即可。

F

不难发现如果要使用毒药,那么一定是在最开始用了若干瓶,然后又去抵消了一个前缀的回复效果,只需要枚举这个前缀是多少然后计算最优情况即可。

G

因为 ww 和最终答案的和都是求最大值,所以可以直接去掉绝对值,这样相当于给 nn 个数负号,nn 个数正号,使得和最大,显然,负号会给到数对中的较小值,正号会给到数对中的较大值,考虑什么时候给正号比给负号优,设第一对给了正号,第二对给了负号,那么给第二对正号更优当且仅当 a1b2<a2b1a_1-b_2<a_2-b_1,发现按照 a+ba+b 排序然后取前 nn 个即可。

J

根据 A,B,CA,B,C 的数量,我们可以求出 AB,BC,ACAB,BC,AC 各自有多少个,以 ABAB 为例,它有 cntA+cntBcntC2\frac{cnt_A+cnt_B-cnt_C}{2} 个,由于 BB 的前面也能接,后面也能接,所以我们优先处理 BB,如果存在划分方案,那么将 BB 的前 cntBCcnt_{BC} 个和 CC 配对,BB 的后 cntABcnt_{AB} 个和 AA 配对,这样一定是不劣的,考虑 ABAB 中用到的 AA ,应该是距离 BB 最近的 AABCBC 同理,这样剩下的 ACAC 一定可以配对,否则不存在划分方案。

K

如果根确定,那这题十分显然,只需要根据叶子节点的大小去搜索即可。

现在问题转化为如何确定根,考虑对于一个结点来说,它要么作为根,要么有一个父亲,考虑与这个点相邻的若干块中,影响这个点的只有最小的叶子最大的那个块,比较这个叶子和当前点谁放在序列上更优即可。

具体实现可以从最小的叶子结点开始往上找根,然后依次更新答案。

L

实际上最多只要两次即可实现,只需要找到一个前缀,让它恰好包含一种字符出现了 nn 次,将后面区间分成两段分别覆盖一种字符即可,于是依次判断能否用 0,10,1 次来实现这个问题,00 次直接判断,11 次用双指针即可。

N

考虑对 aa 数组操作不太好弄,因为不一定每一个 aia_i 都会向下产生贡献,而 bib_i 则不是,如果存在 bib_i,那么它一定是需要被抵消的,所以每次将 bb 数组往上推即可。


seerc2021
https://suzipei.github.io/2022/08/29/seerc2021/
作者
Su_Zipei
发布于
2022年8月29日
许可协议