赛时做出了 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=xi−1+1,yi=yi−1,zi=zi−1。
- 若 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=xi−1,yi=max(xi−1,yi−1+1),zi=zi−1
- 若 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=xi−1,yi=yi−1,zi=max(yi−1,zi−1+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))。卡常后可过本题。