T1:游戏(game)
这个游戏是这样的,你有一个初始序列
S
S
S ,你每次可以选择一段任意长度的连续区间,把他们
+
1
+1
+1 再膜
k
k
k,给定目标序列,你需要尝试用尽量少的操作次数将初始序列变为目标序列。作为一名优秀的 OIer,您认为这个游戏十分 naive,所以您打算撸一个游戏脚本来取到最优解。
一开始以为最多只会加一次 K,结果只有
30
30
30%
设 a[i] 是第 i 位需要加的次数, 令
c
[
i
]
=
a
[
i
]
−
a
[
i
−
1
]
c[i]=a[i]-a[i-1]
c[i]=a[i]−a[i−1];
a
n
s
=
max
i
=
1
n
(
c
[
i
]
,
0
)
ans=\max_{i=1}^{n}(c[i],0)
ans=maxi=1n(c[i],0)
显然 c 数组的取值为
(
−
k
,
k
)
(-k,k)
(−k,k)
考虑模数带来的影响是可以无代价的将一段 a 数组全体
+
k
+k
+k, 对应到 c 数组即为
c
[
l
]
+
k
,
c
[
r
]
−
k
c[l]+k,c[r]-k
c[l]+k,c[r]−k
问题转化为调整 c 数组最小化 ans
仍然考虑贪心解决,显然
l
l
l 只有在
c
[
l
]
c[l]
c[l] 为负时才可能减小
a
n
s
ans
ans, 同样
r
r
r 只在
c
[
r
]
c[r]
c[r] 为正时才有意义
从左向右扫
c
c
c 数组,将
c
[
i
]
+
k
(
c
[
i
]
<
0
)
c[i]+k(c[i]<0)
c[i]+k(c[i]<0) 存入桶中, 对于
>
0
>0
>0 的
c
[
i
]
c[i]
c[i] 在桶中查找能减少的最大值, 如果找到则更新桶, 可以证明这个贪心是正确的复杂度
O
(
n
k
)
O(nk)
O(nk)
T2:蔬菜(vegetable)
您正站在森林中最显眼的一棵树前,一条叫 Skqliao 的人正在树上打盹,他告诉您这棵树是一棵无根树,在第
i
i
i 个点上有
x
x
x 颗蔬菜,如果您想要回去的话就需要收集尽量多的蔬菜。当然乐于助人的 Skqliao 也会帮助您。具体来讲,首先你和 Skqliao 各选择一个不同的起点,接着轮流选定一个与自己相邻的且两人都未经过的点并到达该点。当某人无法移动时,另一人可以继续移动,直到两人都无法移动为止。当你或 Skqliao 经过某点时就可以收集该点所有蔬菜,请你制定合理策略 (包括 Skqliao 选择的初始位置和操作方式) 尝试获得最多的蔬菜。
根据题意,可以发现求的是树上不相交的两条链的最大值
先预处理出
f
[
x
]
,
g
[
x
]
f[x],g[x]
f[x],g[x]
f
[
x
]
f[x]
f[x] 表示经过 x 的最长半链
f
[
x
]
=
m
a
x
(
f
[
t
o
]
)
+
s
[
x
]
f[x]=max(f[to])+s[x]
f[x]=max(f[to])+s[x]
g
[
x
]
g[x]
g[x] 表示在 x 这棵子树中的最长链
g
[
x
]
=
m
a
x
(
g
[
t
o
]
,
f
[
t
o
]
+
f
[
t
o
′
]
+
s
[
i
]
)
g[x]=max(g[to],f[to]+f[to']+s[i])
g[x]=max(g[to],f[to]+f[to′]+s[i]),分两种情况讨论,一种是最长链在
x
x
x 的子树中,另一种是经过 x 的最长半链和次长半链
枚举割边,将这棵树分成两部分,通过经典的提根操作,即可在
O
(
1
)
O(1)
O(1) 的时间内完成
提根时,需要找到 3 条最长的半链,分类讨论子树内的情况,即可知道子树外的最长链
T3:分身术(phantom)
从机房到食堂的地图可以简化为一张
n
n
n 个点
m
m
m 条边的有向图,通过每条边需要一定的时间。机房在
1
1
1 号节点,食堂在
n
n
n 号节点。膜法师 hercier 使用结界将食堂和一些点封锁了起来使其无法通过,如果想通过某个节点,你就必须破坏掉维持这个节点结界的所有结界发生器。幸运的是,你在上一题的未知森林里领悟了分身术,你可以分出无限多的分身去破坏结界发生器,normalgod 想知道你最早什么时候能到达食堂,请你写个程序告诉他。(破坏瞬间完成,分身移动速度与本体相同)
很明显,只考虑结节是拓扑图,然后不考虑结界就是一个单纯的最短路
考虑一边做最短路,一边跑拓扑,一个点能更新其他点必须是它已经被走到并且拓扑向它的点都被走到,更新的时间为最短路的时间和拓扑到的时间的
max
\max
max
该图不能跑 spfa,因为用 spfa 时,拓扑到其他点的时间不应定是最优的会影响到拓扑到的点的更新
迪杰斯特拉多好啊,反正 spfa 死了