Minimizing Maximizer(POJ No.1769)
Maximizer是一个接受
n
n
n 个数作为输入,并输出它们的最大值的装置。这个装置由
m
m
m 个叫做Sorter的装置依次连接而成。第
k
k
k 个Sorter把第
k
−
1
k-1
k−1 个Sorter的输出作为输入,然后将第
s
k
s_k
sk 到第
t
k
t_k
tk 个值进行排序后,保持其余部分不变输出。Maximizer的输入就是第一个Sorter的输入,最后一个Sorter的输出就是Maximizer的输出。从组成Maximizer的Sorter中去掉几个之后,Maximizer有可能还可以正常工作。现在给定Sorter的序列,求其中的最短的一个子序列(可以不连续)使得Maximizer仍然可以正常工作。
(
2
≤
n
≤
50000
,
1
≤
m
≤
500000
,
1
≤
s
k
<
t
k
≤
n
)
(2\leq n \leq 50000,1 \leq m \leq 500000,1 \leq s_k < t_k \leq n)
(2≤n≤50000,1≤m≤500000,1≤sk<tk≤n)
输入
n = 40
m = 6
输出
4
题解
首先考虑一下在什么样的情况下可以正常工作。假设输入的第 i i i 个数是应该输出的最大值。此时,在第一个满足 s k ≤ t k ≤ t k ′ s_k \leq t_k \leq t_{k'} sk≤tk≤tk′ 的Sorter的输出中,这个值被移动到了第 t k t_k tk个位置。
接下去,在第一个满足 s k ′ ≤ t k ≤ t k ′ s_{k'} \leq t_k \leq t_{k'} sk′≤tk≤tk′ 的Sorter的输出中,这个值又被移动到第 t k ′ t_{k'} tk′ 个。不断重复这样的操作,如果最后可以被移动到第 n n n 个,那么就表示Maximizer可以正常工作。
因为只要对i=1
的情况可以正常工作,那么对于任意的
i
i
i都可以正常工作。我们不妨假设输入的第一个数是应该输出的最大值
定义 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示到第 i i i 个Sorter位置,最大值被移动到第 j j j 个位置所需要的最短的子序列的长度( I N F INF INF表示不存在这样的序列)
d p [ 0 ] [ 1 ] = 0 d p [ 0 ] [ j ] = I N F ( j > 1 ) d p [ i + 1 ] [ j ] { d p [ i ] [ j ] ( t ≠ j ) m i n ( d p [ i ] [ j ] , m i n { d p [ i ] [ j ′ ] ∣ s i ≤ j ′ ≤ t i } + 1 ) ( t i = j ) dp[0][1] = 0\\ dp[0][j]=INF(j>1)\\ dp[i+1][j] \begin{cases} dp[i][j](t \neq j)\\ min(dp[i][j], min\{dp[i][j']|s_i \leq j' \leq t_i\}+1)(t_i=j) \end{cases} dp[0][1]=0dp[0][j]=INF(j>1)dp[i+1][j]{dp[i][j](t=j)min(dp[i][j],min{dp[i][j′]∣si≤j′≤ti}+1)(ti=j)
由于这个 D P DP DP 的复杂度是 O ( n m ) O(nm) O(nm) 的,仍然无法在规定时间内求出答案。但是对于 t i ≠ j 时 有 d p [ i + 1 ] [ j ] = d p [ i ] [ j ] t_i \neq j时有dp[i+1][j]=dp[i][j] ti=j时有dp[i+1][j]=dp[i][j] 。如果我我们使用同一个数组不断对自己更新又会怎样呢?
定义 d p [ j ] dp[j] dp[j] 表示最大值被移动到第 j j j 个位置所需要的最短的子序列的长度( I N F INF INF 表示不存在这样的序列)
进行一下初始化:
d
p
[
1
]
=
0
,
d
p
[
j
]
=
I
N
F
(
j
>
1
)
dp[1]=0,dp[j]=INF(j>1)
dp[1]=0,dp[j]=INF(j>1)
对于每个
i
i
i,这样更新:
d
p
[
t
i
]
=
m
i
n
(
d
p
[
t
i
]
,
m
i
n
{
d
p
[
j
′
]
∣
s
i
≤
j
′
≤
t
i
}
+
1
)
dp[t_i]=min(dp[t_i],min\{dp[j']|s_i \leq j' \leq t_i\}+1)
dp[ti]=min(dp[ti],min{dp[j′]∣si≤j′≤ti}+1)
这样,对于每一个 i i i 都只需要更新一个值就可以了。但是可能会认为求解最小值时,最坏的情况下仍然要 O ( n ) O(n) O(n) 的时间,最后复杂度还是 O ( n m ) O(nm) O(nm) 。不过,如果使用之前介绍的线段树来维护,就可以在 O ( m l o g n ) O(m\ log\ n) O(m log n) 的时间内求解了。