Codeforces Educational Round 153
T1,T2,T3
比较简单的题目。
T4
首先存在一个观点:一个位置至多只会被交换一次。因为交换两次的情况可以被某一种交换一次的方案替代。比如 101 101 101 进行 ( 1 , 2 ) , ( 1 , 3 ) (1,2),(1,3) (1,2),(1,3) 两次交换 得到序列 110 110 110,可以使用一次交换 ( 2 , 3 ) (2,3) (2,3) 达到相同的效果。
故我们知道:每个点的颜色最多只会反转一次。我们可以将异色位置对 ( i , j ) (i,j) (i,j) 颜色的交换看成两个分立的过程:将 i i i 的颜色反转,将 j j j 的颜色反转。
考虑最后需要满足的条件:
- 反转的 0 / 1 0/1 0/1 个数相同。
- 10 10 10 子序列的数量变化量 = 原串 1 的数量 × 原串 0 的数量 2 − 原串 01 子序列数量 \displaystyle =\frac{原串 1 的数量 \times 原串 0 的数量}{2}-原串 01 子序列数量 =2原串1的数量×原串0的数量−原串01子序列数量。
设计 DP 状态 F i , j , k F_{i,j,k} Fi,j,k 表示前 i i i 个位置, 0 0 0 反转个数 − - − 1 1 1 反转个数为 j j j, 01 01 01 子序列变化量为 k k k。
转移时间复杂度为 O ( n 4 ) O(n^4) O(n4)。
T5
考虑如下建图:每个间隙向左右建边;对于每种不同种类的空隙建立一个超级源点,并且向所有该种类的点建边。
那么对于每一种询问可能存在两种路径:
- 不进行相同种类的跳转。
- 进行过至少一次相同种类的跳转。
注意到空隙的种类数只有 26 ∗ 26 26*26 26∗26 种,枚举种类 T T T,从其超级源点 S T S_T ST 跑一次单元最短路。接下来检查所有询问经过 S T S_T ST 的情况:即使用种类 T T T 的跳转。
总时间复杂度为 O ( n 2 6 2 ) O(n26^2) O(n262)。
T6
24oi 2023.8.23
做题记录
T1
T2
取模存在性质:
如果
p
≡
q
(
m
o
d
(
A
B
)
)
p\equiv q(\bmod\ (AB))
p≡q(mod (AB)),那么
p
≡
q
(
m
o
d
A
)
p\equiv q(\bmod\ A)
p≡q(mod A)。
考虑题目里同余方程的形式:
x
p
i
≡
q
i
(
m
o
d
∏
p
)
x^{p_i}\equiv q_i(\bmod \prod\ p)
xpi≡qi(mod∏ p)
发现可以在模数上做手脚:
x
p
i
≡
q
i
(
m
o
d
p
i
)
x^{p_i}\equiv q_i(\bmod\ p_i)
xpi≡qi(mod pi)
那么考虑费马小定理有:
x
p
i
−
1
≡
1
(
m
o
d
p
i
)
x
≡
q
i
(
m
o
d
p
i
)
\begin{aligned} x^{p_i-1}&\equiv 1(\bmod\ p_i)\\ x&\equiv q_i(\bmod\ p_i) \end{aligned}
xpi−1x≡1(mod pi)≡qi(mod pi)
那么变成了普通的 CRT 形式。考虑和原问题的关系:
这个转换是向松的方向转化。而 CRT 可以求出
m
o
d
n
\bmod\ n
mod n 下的唯一解。故我们只需要判定这个解是否合法即可。可以暴力检查即可。
T3
构造出的最优解肯定形如这样:耗费若干代价在几个位置放上棋子,然后剩下的连续空段可以不消耗代价填上。
考虑什么样的连续空段是可以
0
0
0 消耗可以填满的。从长度为
1
1
1 的段反推,序列满足这样的递推式:
F
i
=
{
1
(
i
=
1
)
2
F
i
−
1
+
1
(
i
>
1
)
F_i= \begin{cases} &1 &(i=1)\\ &2F_{i-1}+1&(i>1) \end{cases}
Fi={12Fi−1+1(i=1)(i>1)
存在通项
F
i
=
2
i
−
1
F_{i}=2^i-1
Fi=2i−1。
那么对于原棋盘的每一个空段贪心填补即可。
小结
-
思考适当结合所学算法。例如今天的 T 2 T2 T2 在形式上类同 CRT。应该尝试思考如何在形式上转化使得原问题的形式像 CRT 靠近。
-
检查特殊情况。最好在考场写代码的时候就将思考到的特殊情况记录下来。写完容易忘。一定要检查!
-
开场看完所有题目的题面。
24oi 2023.8.24
首先这一场的 T1,T3 是两道非常简单的题目。
T2
容易想到一个状态数为 n 2 n^2 n2 的 DP 做法。设 F i , j F_{i,j} Fi,j 表示考虑前 i i i 个数,最后一个数被改成 j j j,前 i i i 个数改成不降的最小代价。状态数 n 2 n^2 n2 的保证是:存在一种最优方案,使得每一个位置最终的数都是原来的 n n n 个数之一(考虑任取一种最优解,然后进行调整)。
考场做法(在树上为错解,但序列上是正确的)。
考虑对于原始序列 a a a, a a a 升序排序后为 b b b,贪心构造目标序列 c c c,最小化 ∑ ∣ a i − c i ∣ \sum |a_i-c_i| ∑∣ai−ci∣。由上述的结论有存在一种 c c c 的构造形如若干个 b 1 b_1 b1 后接若干个 b 2 b_2 b2 ⋯ \cdots ⋯ 后接若干个 b n b_n bn。那么先将 c [ 1 , n ] c[1,n] c[1,n] 抬升到 b 1 b_1 b1。考虑抬升到 b 2 b_2 b2 的区间一定是抬升到 b 1 b_1 b1 的一个后缀。其后依次类推。
对于 i i i 位置考虑后缀 a [ i : ] a[i:] a[i:],最大能使其更优的抬升量为 p p p。考虑如何确定 p p p。有如果存在 a [ i : ] a[i:] a[i:] 的前缀 a [ i : j ] a[i:j] a[i:j] 满足其中 < p < p <p 的个数 > > > a [ i : j ] a[i:j] a[i:j] 中 > p >p >p 的个数,那么 i i i 抬升到 p p p 是不优的。
发现在上述的这种情况中,将 a [ i : j ] a[i:j] a[i:j] 的抬升量向下调整 − 1 -1 −1 更优。这样对于 a [ j + 1 : ] a[j+1:] a[j+1:] 的限制更松:整体答案不会更劣。故得证。
那么有 c i = m a x j ≤ i p j c_i=max_{j\le i}p_j ci=maxj≤ipj。故快速确定 p i p_i pi 即可。这个是可做的。无法扩展到树上。
正解
颠覆常识的 DP 优化。其基于最开始说的 n 2 n^2 n2 的 DP。事实上,其不依赖值域取到 n n n 个数的值域:也就是说,其基于的是暴力 O ( n V ) O(nV) O(nV) 的 DP。
沿用
F
i
,
j
F_{i,j}
Fi,j,
j
j
j 取遍整个值域。考虑数组
G
i
G_i
Gi,
G
i
,
j
G_{i,j}
Gi,j 表示
min
k
≤
i
F
i
,
k
\min_{k\le i}F_{i,k}
mink≤iFi,k。
结论:
G
i
G_i
Gi 是一个
∣
斜率
∣
|斜率|
∣斜率∣ 不升的下凸壳。
如图所示:当
p
1
<
p
2
p_1<p_2
p1<p2 时
G
i
+
1
G_{i+1}
Gi+1 显然仍然满足凸壳性质。当
p
2
<
p
1
p_2<p_1
p2<p1 时
p
2
p_2
p2 之前部分斜率绝对值变大,之后的部分斜率绝对值变小,同样满足凸壳性质。由于我们维护的是前缀
min
\min
min,所以在后面有斜率为
0
0
0,不会有后面翘起来的情况。
如何快速维护凸壳和最优 DP 决策点?考虑一种神仙做法:使用堆。堆中存储所有凸壳的拐点。关于刻画斜率:由于斜率绝对值单调不升,那么通过将同一个拐点多次插入堆模拟斜率。具体的,我们令堆中两个相邻位置构成的斜线 [ x i , x i + 1 ] [x_i,x_{i+1}] [xi,xi+1] 的斜率为堆中 ≥ x i + 1 \ge x_{i+1} ≥xi+1 的拐点个数。设插入 v v v,我们考虑如何设计转移:
-
v
≥
q
.
t
o
p
(
)
v\ge q.top()
v≥q.top()
直接将 v v v p u s h push push 进入 q q q 即可。答案不变。 -
v
<
q
.
t
o
p
(
)
v< q.top()
v<q.top()
答案增加 q . t o p ( ) − v q.top()-v q.top()−v。同时凸壳中 ≥ v \ge v ≥v 的部分斜率都 + 1 +1 +1,那么需要弹出最大的拐点(相当于给 ≤ q . t o p ( ) \le q.top() ≤q.top() 的部分斜率 + 1 +1 +1),然后 p u s h push push 两次 v v v,相当于给凸壳中 ≤ v \le v ≤v 的部分斜率 − 2 -2 −2。
容易拓展到树上。
24oi 2023.8.25
T1
思维水平不高导致的。
满足
a
1
≤
a
2
≤
a
3
≤
⋯
≤
a
n
a_1\le a_2\le a_3\le \cdots \le a_n
a1≤a2≤a3≤⋯≤an,等价于
a
1
≤
a
2
a
2
≤
a
3
⋮
\begin{aligned} a _1\le a_2\\ a_2\le a_3\\ \vdots\\ \end{aligned}
a1≤a2a2≤a3⋮