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