代码能力还是太差
C.Museums Tour
明示拆点 i → ( i , j ) ( 0 ≤ j < d ) i\to (i,j)(0\leq j<d) i→(i,j)(0≤j<d),缩点后拓扑排序 d p dp dp。
发现若存在 ( i , j ) → ( i , j ′ ) (i,j)\to (i,j') (i,j)→(i,j′) ,则必然 ( i , j ′ ) → ( i , j ) (i,j')\to (i,j) (i,j′)→(i,j)可达,大小为 d gcd ( d , j ′ − j ) \dfrac{d}{\gcd(d,j'-j)} gcd(d,j′−j)d,所以 i i i所有的 S C C SCC SCC指向的后继中必然不存在 ( i , k ) ( 0 ≤ k < d ) (i,k)(0\leq k<d) (i,k)(0≤k<d)。所以保证了每个点的贡献只会被算 1 1 1次。
考虑同一个SCC中的所有点,若存在一个简单环使得 gcd ( d , l e n ) \gcd(d,len) gcd(d,len)最小,设最小值为 g g g,则若 S C C SCC SCC中存在 ( i , j ) (i,j) (i,j),那么所有 ( i , j + k ⋅ g ) (i,j+k·g) (i,j+k⋅g)都在这个 S C C SCC SCC中。
任意选 S C C SCC SCC中的一个点 x x x做根求生成树,即得到所有简单环的 g g g,预处理出 0 − ( g − 1 ) 0-(g-1) 0−(g−1)时刻从 x x x出发能访问的点数。
两个 S C C SCC SCC之间的连边 g ′ = gcd ( g u , g v ) g'=\gcd(g_u,g_v) g′=gcd(gu,gv),保证边数是 O ( m ⋅ d ) O(m·d) O(m⋅d)的。
注意在实现过程中不需要真的拆点。
细节比较多,具体还是看yyb’s blog吧
D.Cooperative Game
好妙!
考虑如何用两个点的移动找到 t t t:
让两个点同时移动,点 1 1 1每次移动,点 2 2 2每两次移动一格,直到两点相遇。
具体分析这个过程:设当
2
2
2移动
t
t
t格时,
1
1
1在
t
+
p
t+p
t+p格,那么
t
%
c
=
p
t\% c=p
t%c=p,再走
c
−
p
c-p
c−p轮
1
1
1追上
2
2
2,
1
,
2
1,2
1,2位置均为
t
+
c
−
p
t+c-p
t+c−p。然后所有点一起向前移:其它点
t
t
t轮后到达位置
t
t
t,
1
,
2
1,2
1,2点
t
t
t轮后到达
t
+
c
−
p
+
t
%
c
≡
t
t+c-p+t\%c\equiv t
t+c−p+t%c≡t。
次数 3 t + 2 c − 2 p 3t+2c-2p 3t+2c−2p
E.Train Car Selection
如果在前端插入,后面的点一定不会是最优点。
所以只有在几轮没有前段插入的修改后最优值可能为后面的一些点,每个点的编号看做 x x x坐标,常数项看做 y y y坐标,则只需要维护一个下左凸壳,每次暴力弹栈顶(注意第一个点是 ( 0 , 0 ) (0,0) (0,0))。
可以结合下图理解
F. Matches Are Not a Child’s Play
操作2,3是等价的。
对于一次
x
x
x的修改,设修改前优先级最大的点为
y
y
y,发现燃烧次序的改变很有规律:
x
→
y
x\to y
x→y路径上的点倒序构成序列的后半部分
(
y
→
x
)
(y\to x)
(y→x),其余点的相对次序不变构成前半部分。
于是把一次修改操作相当于把
x
→
y
x\to y
x→y链染上新的一种颜色。
询问点的次序相当于询问颜色编号比它小的所有的链的总点数+同色点优先级比它小的点数。
把当前优先级最大的点作为根,修改操作就可以用
L
C
T
LCT
LCT的
m
a
k
e
r
o
o
t
makeroot
makeroot维护了。
BIT维护每个颜色编号的点数,询问相当于求颜色编号前缀和-当前点splay到根后左儿子大小。