CF1609 部分题解

赛时做出了 ABCDE,没有做出 FGH;目前已补掉了 F,尚未补掉 G,H。

A

b i b_i bi a i a_i ai 所含质因子 2 2 2 的个数, c i = a i 2 b i c_i=\frac {a_i} {2^{b_i}} ci=2biai。不难发现,调整过程等价于将一共的 S = ∑ i = 1 n b i S=\sum_{i=1}^n b_i S=i=1nbi 个质因子 2 2 2 重新分配给所有的 c c c,使得所有值之和最大。

根据贪心策略,将 S S S 全部分配给最大的 c c c 即可。

B

不难发现,最少删除次数就是 abc 以子串形式出现的次数。于是,我们只要在询问过程中,动态更新这个值即可。

时间复杂度 O ( ∑ ( n + q ) ) O(\sum (n+q)) O((n+q))

C

为方便叙述,令 b i = 1 b_i=1 bi=1 当且仅当 a i a_i ai 为质数, b i = 0 b_i=0 bi=0 当且仅当 a i = 1 a_i=1 ai=1 b i = − 1 b_i=-1 bi=1 当且仅当 a i a_i ai 为合数。

看到下标为等差数列的问题,不难想到将 a a a 分成独立的 e e e 类,第 i i i 类为 { b i , b i + e , ⋯   } \{b_i,b_{i+e},\cdots\} {bi,bi+e,}。于是,问题转化为: 对于一个固定的序列 c c c,求其有多少个子区间不包含 − 1 -1 1 且和为 1 1 1。显然,将 c c c 中所有值为 − 1 -1 1 的位删去,再对每个分裂出的区间做前缀和,最后再用桶扫描一遍计算对答案的贡献即可。

时间复杂度 O ( ∑ n ) O(\sum n) O(n)

D

首先,图中不会有环。

其次,令 S i S_i Si 为第 i i i 个连通块所包含的点集,那么对于每个 S i S_i Si 在其内部连成一个菊花图必定最优。因此,答案就是 max ⁡ i { S i } − 1 \max_i \{S_i\}-1 maxi{Si}1。于是,问题转化为: 如何构造图,使其最大的连通块最大。

依次扫描每一条边 ( x , y ) (x,y) (x,y),并分类讨论:

  • x , y x,y x,y 属于不同连通块,则连一条跨越这两个连通块的边;
  • x , y x,y x,y 属于同个连通块,那么将 c n t cnt cnt 1 1 1

可以发现,当前的 c n t cnt cnt 就是我们可以随意钦定的边数;不难想到,用这 c n t cnt cnt 条边将前 c n t + 1 cnt+1 cnt+1最大的连通块连接起来,即可最大化 max ⁡ i { S i } \max_i \{S_i\} maxi{Si}

并查集维护即可。时间复杂度 O ( n 2 ) O(n^2) O(n2)

若使用权值线段树维护各个连通块的大小,并每次通过线段树上二分求出答案,则总复杂度可以被优化到 O ( n log ⁡ n ) O(n \log n) O(nlogn)

E

算法一

考虑 dp \text{dp} dp

x i x_i xi 表示,看了 s [ 1 , i ] s[1,i] s[1,i],使其中不存在 a 的最少删除次数。
y i y_i yi 表示,看了 s [ 1 , i ] s[1,i] s[1,i],使其中不存在子序列 ab 的最少删除次数。
z i z_i zi 表示,看了 s [ 1 , i ] s[1,i] s[1,i],使其中不存在子序列 abc 的最少删除次数。

转移如下:

  • a i = 0 a_i=0 ai=0,则 x i = x i − 1 + 1 , y i = y i − 1 , z i = z i − 1 x_i=x_{i-1}+1,y_i=y_{i-1},z_i=z_{i-1} xi=xi1+1,yi=yi1,zi=zi1
  • a i = 1 a_i=1 ai=1,则 x i = x i − 1 , y i = max ⁡ ( x i − 1 , y i − 1 + 1 ) , z i = z i − 1 x_i=x_{i-1},y_i=\max(x_{i-1},y_{i-1}+1),z_i=z_{i-1} xi=xi1,yi=max(xi1,yi1+1),zi=zi1
  • a i = 2 a_i=2 ai=2,则 x i = x i − 1 , y i = y i − 1 , z i = max ⁡ ( y i − 1 , z i − 1 + 1 ) x_i=x_{i-1},y_i=y_{i-1},z_i=\max(y_{i-1},z_{i-1}+1) xi=xi1,yi=yi1,zi=max(yi1,zi1+1)

边界: x 0 = y 0 = z 0 = 0 x_0=y_0=z_0=0 x0=y0=z0=0
答案: z n z_n zn

每次修改都跑一遍 dp \text{dp} dp,则总复杂度 O ( q n ) O(qn) O(qn),无法通过。

算法二

采用矩阵表示上述转移,并使用线段树维护矩阵乘法,则时间复杂度为 O ( q log ⁡ n × 3 3 ) O(q \log n \times 3^3) O(qlogn×33),可以通过本题。

F

我竟然没有发现我的做法的复杂度是正确的!!1

w i = popcount ( a i ) w_i=\text{popcount}(a_i) wi=popcount(ai) W = 59 W=59 W=59。我们在 [ 0 , W ] [0,W] [0,W] 中枚举一个 x x x,表示区间最值的 w w w 均为 x x x

为方便叙述,令 i i i 为优秀位置,当且仅当 w i = x w_i=x wi=x。同时,令 t i t_i ti 表示 [ i , r ] [i,r] [i,r] a a a 最大的位置的 w w w 是否为 x x x 以及 a a a 最小的 w w w 是否为 x x x——若均满足则 t i = 2 t_i=2 ti=2,只满足一个则 t i = 1 t_i=1 ti=1,否则 t i = 0 t_i=0 ti=0

考虑从左往右扫描序列(令当前扫描到了 r r r),并使用单调栈+线段树维护 t t t。具体来说,我们使用一个表示最小值的单调栈,维护一个递增序列;每当新看到一个数的时候,我们先进行弹栈,并对于每个弹出的值进行区间加 1 1 1 或区间减 1 1 1(因为一个新的区间最小值替代掉了原来的区间最小值,如果优秀的替换了不优秀的那么区间加 1 1 1,如果不优秀的替换掉了优秀的那么区间减 1 1 1)。另外也要用一个表示最大值的单调栈进行同样的处理。不难发现,这里只要求维护区间修改,查询区间中 2 2 2 的数量,线段树显然可以胜任。

那么这个复杂度是什么的呢?我赛时一直以为是 O ( n log ⁡ n log ⁡ M ) O(n \log n \log M) O(nlognlogM) 的,实则不然。下面便是复杂度分析:

  • 先考虑询问。显然,询问都是全局的,而一共有 O ( n log ⁡ M ) O(n \log M) O(nlogM) 次询问,所以这一部分是 O ( n log ⁡ M ) O(n \log M) O(nlogM) 的。
  • 再考虑修改。
    • 优秀变为不优秀: 一个优秀的值被弹出。显然在固定了 x x x 后,优秀的值只会被弹出一次,而对于 x = 0 , 1 , ⋯   , M x=0,1,\cdots,M x=0,1,,M 所对应的优秀值个数之和恰好是 n n n,所以均摊下来这一部分的复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的。
    • 不优秀变为优秀: 一个优秀的值被加入。与上述分析同理,这一部分的复杂度也是 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的。

因此,总时间复杂度是 O ( n ( log ⁡ n + log ⁡ M ) ) O(n(\log n+\log M)) O(n(logn+logM))。卡常后可过本题。

你可能感兴趣的:(动态规划,数据结构(线段树,平衡树,主席树,LCT,树套树等),图论,算法,动态规划)