题目链接 游记链接
吐槽
我开场第一个开的题就是这个,误判断以为是个我不会的中档贪心题,结果扔给 djq 他都想了好久,然后我就自闭了 2333
题解
真·hard 神题,给出题人点赞!接下来大概就是把英文题解翻译了一遍吧,顺便补了一点证明。
观察
最初始的贪心部分,相信大家都想到了。我们把怪物分成
A
i
>
B
i
A_i > B_i
A i > B i 和
A
i
≤
B
i
A_i \le B_i
A i ≤ B i 的部分,分别记为集合
S
,
T
S,T
S , T ,那么有以下性质:
最终方案任意
T
T
T 集合的元素必然在
S
S
S 集合之前。
最终方案
T
T
T 集合的元素是按照
A
i
A_i
A i 从小到大排序的。这个比较显然,交换一组
A
i
>
A
j
(
i
<
j
)
A_i>A_j(i<j)
A i > A j ( i < j ) 显然不会更劣。
最终方案
S
S
S 集合中的元素是按照
B
i
B_i
B i 从大到小排序的。证明方法类似,交换一组
B
i
<
B
j
(
i
<
j
)
B_i<B_j(i<j)
B i < B j ( i < j ) 不会使答案更劣。
于是整道题就被我们分成了几部分:
对于任意
K
K
K ,计算出在
S
S
S 中选
K
K
K 个怪兽需要花费的最小代价。
对于任意
K
K
K ,计算出在
T
T
T 中选
K
K
K 个怪兽需要花费的最小代价。
合并以上两部分的答案。
其中第一部分最难。
第一部分
考虑一个 trival 的 dp,把
S
S
S 按照
B
B
B 从大到小排序,
f
(
i
,
j
)
f(i,j)
f ( i , j ) 表示当前考虑了最后
i
i
i 个元素,选择
j
j
j 个所需要的最小代价。那么显然有如下 dp 方程:
f
(
i
,
j
)
=
min
{
max
{
f
(
i
−
1
,
j
−
1
)
−
B
i
,
0
}
+
A
i
,
f
(
i
−
1
,
j
)
}
f(i,j)=\min\{\max\{f(i-1,j-1)-B_i,0\}+A_i,f(i-1,j)\}
f ( i , j ) = min { max { f ( i − 1 , j − 1 ) − B i , 0 } + A i , f ( i − 1 , j ) }
仔细分析一下这个 dp 方程,我们发现对于一个
i
i
i ,它有四种不同的转移:
若
f
(
i
−
1
,
j
)
≤
B
i
f(i-1,j) \le B_i
f ( i − 1 , j ) ≤ B i ,那么对于任意
k
≥
i
k \ge i
k ≥ i ,都有
f
(
k
,
j
)
=
f
(
i
−
1
,
j
)
f(k,j)=f(i-1,j)
f ( k , j ) = f ( i − 1 , j ) 。因为我们按照
B
i
B_i
B i 从大到小排序,后面的
B
k
B_k
B k 只会更大。
若
f
(
i
−
1
,
j
)
∈
(
B
i
,
A
i
]
f(i-1,j) \in (B_i,A_i]
f ( i − 1 , j ) ∈ ( B i , A i ] ,则
f
(
i
,
j
)
=
f
(
i
−
1
,
j
)
f(i,j)=f(i-1,j)
f ( i , j ) = f ( i − 1 , j ) 。
若
f
(
i
−
1
,
j
)
>
A
i
f(i-1,j)>A_i
f ( i − 1 , j ) > A i 且
f
(
i
−
1
,
j
)
<
f
(
i
−
1
,
j
−
1
)
+
A
i
−
B
i
f(i-1,j) < f(i-1,j-1)+A_i-B_i
f ( i − 1 , j ) < f ( i − 1 , j − 1 ) + A i − B i ,则
f
(
i
,
j
)
=
f
(
i
−
1
,
j
)
f(i,j)=f(i-1,j)
f ( i , j ) = f ( i − 1 , j ) 。
若
f
(
i
−
1
,
j
)
>
A
i
f(i-1,j)>A_i
f ( i − 1 , j ) > A i 且
f
(
i
−
1
,
j
)
≥
f
(
i
−
1
,
j
−
1
)
+
A
i
−
B
i
f(i-1,j) \ge f(i-1,j-1)+A_i-B_i
f ( i − 1 , j ) ≥ f ( i − 1 , j − 1 ) + A i − B i ,则
f
(
i
,
j
)
=
max
{
0
,
f
(
i
−
1
,
j
−
1
)
−
B
i
}
+
A
i
f(i,j)=\max\{0,f(i-1,j-1)-B_i\}+A_i
f ( i , j ) = max { 0 , f ( i − 1 , j − 1 ) − B i } + A i 。 补充说明:我感觉这里
f
(
i
−
1
,
j
−
1
)
f(i-1,j-1)
f ( i − 1 , j − 1 ) 是有可能
≤
B
i
\le B_i
≤ B i 的,但是题解好像并没有这么写(如果有错误请指出 /kel)。但是判断条件确实不需要带
max
\max
max ,因为
f
(
i
−
1
,
j
−
1
)
≤
B
i
f(i-1,j-1) \le B_i
f ( i − 1 , j − 1 ) ≤ B i 只会让这个条件必然满足。
引理: 令
j
0
=
min
{
j
∣
f
(
i
,
j
)
>
B
i
}
j_0=\min\{j|f(i,j) > B_i\}
j 0 = min { j ∣ f ( i , j ) > B i } ,那么对于任意的
j
0
<
j
<
i
j_0 < j < i
j 0 < j < i ,都有
f
(
i
,
j
+
1
)
−
f
(
i
,
j
)
≥
f
(
i
,
j
)
−
f
(
i
,
j
−
1
)
f(i,j+1)-f(i,j) \ge f(i,j)-f(i,j-1)
f ( i , j + 1 ) − f ( i , j ) ≥ f ( i , j ) − f ( i , j − 1 ) ,并且
f
(
i
,
j
0
+
1
)
−
f
(
i
,
j
0
)
≥
f
(
i
,
j
0
)
−
B
i
f(i,j_0+1)-f(i,j_0) \ge f(i,j_0)-B_i
f ( i , j 0 + 1 ) − f ( i , j 0 ) ≥ f ( i , j 0 ) − B i 。即删掉所有
f
(
i
,
j
)
≤
B
i
f(i,j) \le B_i
f ( i , j ) ≤ B i ,并且在开头补一个
B
i
B_i
B i ,则剩下的东西是个下凸函数。
证明前的准备: 两条显然的不等式,
f
(
i
,
j
)
≤
f
(
i
−
1
,
j
)
f(i,j) \le f(i-1,j)
f ( i , j ) ≤ f ( i − 1 , j ) ,
f
(
i
,
j
)
≥
f
(
i
,
j
−
1
)
f(i,j) \ge f(i,j-1)
f ( i , j ) ≥ f ( i , j − 1 ) 。
接下来的证明都是博主 yy 的,如果有伪证请指出
证明: 考虑数学归纳,
i
=
1
i=1
i = 1 时显然满足。我们首先证明
f
(
i
,
j
0
+
1
)
−
f
(
i
,
j
0
)
≥
f
(
i
,
j
0
)
−
B
i
f(i,j_0+1)-f(i,j_0) \ge f(i,j_0)-B_i
f ( i , j 0 + 1 ) − f ( i , j 0 ) ≥ f ( i , j 0 ) − B i ,首先我们有
f
(
i
,
j
0
−
1
)
=
f
(
i
−
1
,
j
0
−
1
)
≤
B
i
f(i,j_0-1)=f(i-1,j_0-1) \le B_i
f ( i , j 0 − 1 ) = f ( i − 1 , j 0 − 1 ) ≤ B i ,这是因为
f
(
i
,
j
0
−
1
)
f(i,j_0-1)
f ( i , j 0 − 1 ) 不可能从情况 4 转移过来,否则就会
≥
A
i
\ge A_i
≥ A i 。我们分类讨论一下:
f
(
i
,
j
0
)
=
max
{
0
,
f
(
i
−
1
,
j
0
−
1
)
−
B
i
}
+
A
i
f(i,j_0)=\max\{0,f(i-1,j_0-1)-B_i\}+A_i
f ( i , j 0 ) = max { 0 , f ( i − 1 , j 0 − 1 ) − B i } + A i 且
f
(
i
,
j
0
+
1
)
=
f
(
i
−
1
,
j
0
)
−
B
i
+
A
i
f(i,j_0+1)=f(i-1,j_0)-B_i+A_i
f ( i , j 0 + 1 ) = f ( i − 1 , j 0 ) − B i + A i (此时有
f
(
i
−
1
,
j
0
)
≥
f
(
i
,
j
0
)
≥
B
i
f(i-1,j_0) \ge f(i,j_0) \ge B_i
f ( i − 1 , j 0 ) ≥ f ( i , j 0 ) ≥ B i ),即他们俩都是通过情况 4 转移过来的。 由于
f
(
i
−
1
,
j
0
−
1
)
≤
B
i
f(i-1,j_0-1) \le B_i
f ( i − 1 , j 0 − 1 ) ≤ B i ,因此
f
(
i
,
j
0
)
=
A
i
f(i,j_0)=A_i
f ( i , j 0 ) = A i ,显然
f
(
i
,
j
0
)
−
B
i
≤
f
(
i
−
1
,
j
0
)
−
B
i
≤
f
(
i
,
j
0
+
1
)
−
A
i
f(i,j_0)-B_i \le f(i-1,j_0)-B_i \le f(i,j_0+1)-A_i
f ( i , j 0 ) − B i ≤ f ( i − 1 , j 0 ) − B i ≤ f ( i , j 0 + 1 ) − A i 。
f
(
i
,
j
0
)
=
f
(
i
−
1
,
j
0
)
,
f
(
i
,
j
0
+
1
)
=
f
(
i
−
1
,
j
0
)
−
B
i
+
A
i
f(i,j_0)=f(i-1,j_0),f(i,j_0+1)=f(i-1,j_0)-B_i+A_i
f ( i , j 0 ) = f ( i − 1 , j 0 ) , f ( i , j 0 + 1 ) = f ( i − 1 , j 0 ) − B i + A i ,此种情况
f
(
i
,
j
0
+
1
)
−
f
(
i
,
j
0
)
=
A
i
−
B
i
f(i,j_0+1)-f(i,j_0)=A_i-B_i
f ( i , j 0 + 1 ) − f ( i , j 0 ) = A i − B i 。根据转移条件,我们有
f
(
i
,
j
0
)
≤
f
(
i
−
1
,
j
0
)
<
f
(
i
−
1
,
j
0
−
1
)
+
A
i
−
B
i
≤
A
i
f(i,j_0) \le f(i-1,j_0) < f(i-1,j_0-1)+A_i-B_i \le A_i
f ( i , j 0 ) ≤ f ( i − 1 , j 0 ) < f ( i − 1 , j 0 − 1 ) + A i − B i ≤ A i ,因此也成立。
f
(
i
,
j
0
=
f
(
i
−
1
,
j
0
)
,
f
(
i
,
j
0
+
1
)
=
f
(
i
−
1
,
j
0
+
1
)
f(i,j_0=f(i-1,j_0),f(i,j_0+1)=f(i-1,j_0+1)
f ( i , j 0 = f ( i − 1 , j 0 ) , f ( i , j 0 + 1 ) = f ( i − 1 , j 0 + 1 ) ,归纳一下,则
f
(
i
,
j
0
+
1
)
−
f
(
i
,
j
0
)
=
f
(
i
−
1
,
j
0
+
1
)
−
f
(
i
−
1
,
j
0
)
≥
f
(
i
−
1
,
j
0
)
−
max
{
B
i
−
1
,
f
(
i
−
1
,
j
0
−
1
)
}
≥
f
(
i
,
j
0
)
−
B
i
f(i,j_0+1)-f(i,j_0)=f(i-1,j_0+1)-f(i-1,j_0) \ge f(i-1,j_0)-\max\{B_{i-1},f(i-1,j_0-1)\} \ge f(i,j_0)-B_i
f ( i , j 0 + 1 ) − f ( i , j 0 ) = f ( i − 1 , j 0 + 1 ) − f ( i − 1 , j 0 ) ≥ f ( i − 1 , j 0 ) − max { B i − 1 , f ( i − 1 , j 0 − 1 ) } ≥ f ( i , j 0 ) − B i 。
其实接下来对于任意的
j
0
<
j
<
i
j_0 < j < i
j 0 < j < i ,都有
f
(
i
,
j
+
1
)
−
f
(
i
,
j
)
≥
f
(
i
,
j
)
−
f
(
i
,
j
−
1
)
f(i,j+1)-f(i,j) \ge f(i,j)-f(i,j-1)
f ( i , j + 1 ) − f ( i , j ) ≥ f ( i , j ) − f ( i , j − 1 ) 反而好证一些了。我们考虑一个分界点
t
t
t 使得对于
j
≥
t
j \ge t
j ≥ t 都是从情况 4 转移来的,否则都是从 1,2,3 转移来的。首先对于
j
<
t
j<t
j < t ,
f
(
i
,
j
)
−
f
(
i
,
j
−
1
)
≥
f
(
i
−
1
,
j
)
−
f
(
i
−
1
,
j
−
1
)
≥
f
(
i
−
1
,
j
−
1
)
−
f
(
i
−
1
,
j
−
2
)
≥
f
(
i
,
j
−
1
)
−
f
(
i
,
j
−
2
)
f(i,j)-f(i,j-1) \ge f(i-1,j)-f(i-1,j-1) \ge f(i-1,j-1)-f(i-1,j-2) \ge f(i,j-1)-f(i,j-2)
f ( i , j ) − f ( i , j − 1 ) ≥ f ( i − 1 , j ) − f ( i − 1 , j − 1 ) ≥ f ( i − 1 , j − 1 ) − f ( i − 1 , j − 2 ) ≥ f ( i , j − 1 ) − f ( i , j − 2 ) 。注意这里不会有
f
(
i
−
1
,
j
−
2
)
≤
B
i
−
1
f(i-1,j-2) \le B_{i-1}
f ( i − 1 , j − 2 ) ≤ B i − 1 的情况,否则就会有
f
(
i
,
j
−
2
)
≤
B
i
f(i,j-2) \le B_i
f ( i , j − 2 ) ≤ B i 了,不属于这里讨论的范围。
对于分界点
t
t
t ,有
f
(
i
,
t
)
−
f
(
i
,
t
−
1
)
=
A
i
−
B
i
f(i,t)-f(i,t-1)=A_i-B_i
f ( i , t ) − f ( i , t − 1 ) = A i − B i ,根据转移条件,我们有
f
(
i
−
1
,
t
−
1
)
−
f
(
i
−
1
,
t
−
2
)
<
A
i
−
B
i
f(i-1,t-1)-f(i-1,t-2)<A_i-B_i
f ( i − 1 , t − 1 ) − f ( i − 1 , t − 2 ) < A i − B i ,即
f
(
i
,
t
−
1
)
−
f
(
i
,
t
−
2
)
<
A
i
−
B
i
f(i,t-1)-f(i,t-2)<A_i-B_i
f ( i , t − 1 ) − f ( i , t − 2 ) < A i − B i 。类似的,也有
f
(
i
,
t
+
1
)
−
f
(
i
,
t
)
=
f
(
i
−
1
,
t
)
−
f
(
i
−
1
,
t
−
1
)
≥
A
i
+
B
i
f(i,t+1)-f(i,t)=f(i-1,t)-f(i-1,t-1) \ge A_i+B_i
f ( i , t + 1 ) − f ( i , t ) = f ( i − 1 , t ) − f ( i − 1 , t − 1 ) ≥ A i + B i 。
对于
j
>
t
j>t
j > t ,我们有
f
(
i
,
j
+
1
)
−
f
(
i
,
j
)
=
f
(
i
−
1
,
j
)
−
f
(
i
−
1
,
j
−
1
)
≥
f
(
i
−
1
,
j
−
1
)
−
f
(
i
−
1
,
j
−
2
)
=
f
(
i
,
j
)
−
f
(
i
,
j
−
1
)
f(i,j+1)-f(i,j)=f(i-1,j)-f(i-1,j-1) \ge f(i-1,j-1)-f(i-1,j-2)=f(i,j)-f(i,j-1)
f ( i , j + 1 ) − f ( i , j ) = f ( i − 1 , j ) − f ( i − 1 , j − 1 ) ≥ f ( i − 1 , j − 1 ) − f ( i − 1 , j − 2 ) = f ( i , j ) − f ( i , j − 1 ) 。
证毕。
因此扔掉
≤
B
i
\le B_i
≤ B i 的部分,并在最前面补个
B
i
B_i
B i ,确实是个上凸函数。然后就是比较 naive 的部分了,直接上个优先队列维护差分数组,每次扔掉
≤
B
i
\le B_i
≤ B i 的部分,并且更新一下第一个值(因为第一个点从
B
i
−
1
B_{i-1}
B i − 1 变成
B
i
B_i
B i 了)。然后再往优先队列里扔一个
A
i
−
B
i
A_i-B_i
A i − B i (决策分界点的差分)即可。复杂度
O
(
n
log
n
)
O(n \log n)
O ( n log n ) 。
第二部分
这个部分我都在想要不要额外开一个小标题,由于强迫症我还是开了。
由于
A
i
≤
B
i
A_i \le B_i
A i ≤ B i ,根据观察,直接选择
K
K
K 个最小的
A
i
A_i
A i 即可。
第三部分
我们知道了选择
i
i
i 个集合
T
T
T 中元素的最小代价
c
i
c_i
c i ,即初始能量在
[
c
i
,
c
i
+
1
)
[c_i,c_{i+1})
[ c i , c i + 1 ) 时我们都只能选
i
i
i 个。于是我们就知道了如果初始能量在这段区间中,能量会增加多少,设为
d
i
d_i
d i 。我们找到所有
j
j
j 表示在
S
S
S 中选
j
j
j 个,并且
i
+
j
i+j
i + j 这个个数还没有被计算过的
j
j
j ,
f
j
≤
c
i
+
1
+
d
i
−
1
f_j \le c_{i+1}+d_i-1
f j ≤ c i + 1 + d i − 1 的,那么它需要的初始代价就是
max
{
c
i
,
f
j
−
d
i
}
\max\{c_i,f_j-d_i\}
max { c i , f j − d i } 。
由于
c
i
,
d
i
c_i,d_i
c i , d i 显然都单增,因此可以做到线性时间。
综上,我们就得到了一个复杂度
O
(
n
log
n
)
O(n \log n)
O ( n log n ) 的做法。
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
template < typename T> void chkmax ( T & a, const T & b) { a = a < b ? b : a; }
template < typename T> void chkmin ( T & a, const T & b) { a = a < b ? a : b; }
const int MAXN = 300005 , MOD = 1e9 + 7 ;
struct Data { int a, b; } S[ MAXN] , T[ MAXN] ;
priority_queue< int , vector< int > , greater< int > > pq;
int aa[ MAXN] , bb[ MAXN] , n, C;
LL f[ MAXN] , c[ MAXN] , d[ MAXN] ;
bool cmpa ( const Data & a, const Data & b) { return a. a < b. a; }
bool cmpb ( const Data & a, const Data & b) { return a. b < b. b; }
int main ( ) {
for ( scanf ( "%d" , & C) ; C-- ; ) {
scanf ( "%d" , & n) ;
int ns = 0 , nt = 0 ;
for ( int i = 1 ; i <= n; i++ ) scanf ( "%d" , aa + i) ;
for ( int i = 1 ; i <= n; i++ ) scanf ( "%d" , bb + i) ;
for ( int i = 1 ; i <= n; i++ ) {
int a = aa[ i] , b = bb[ i] ;
if ( a <= b) T[ ++ nt] = Data { a, b } ;
else S[ ++ ns] = Data { a, b } ;
}
sort ( S + 1 , S + 1 + ns, cmpb) ;
sort ( T + 1 , T + 1 + nt, cmpa) ;
int cnt = 0 ;
LL low = 0 ;
for ( int i = 1 ; i <= ns; i++ ) {
while ( ! pq. empty ( ) ) {
int sum = pq. top ( ) + low;
if ( sum > S[ i] . b) break ;
low = sum;
f[ ++ cnt] = low;
pq. pop ( ) ;
}
if ( ! pq. empty ( ) ) {
int sum = pq. top ( ) + low - S[ i] . b;
pq. pop ( ) ;
pq. push ( sum) ;
}
pq. push ( S[ i] . a - S[ i] . b) ;
low = S[ i] . b;
}
for ( ; ! pq. empty ( ) ; pq. pop ( ) )
f[ ++ cnt] = ( low + = pq. top ( ) ) ;
for ( int i = 1 ; i <= nt; i++ ) {
c[ i] = max ( T[ i] . a - c[ i - 1 ] - d[ i - 1 ] , 0ll ) + c[ i - 1 ] ;
d[ i] = d[ i - 1 ] + T[ i] . b - T[ i] . a;
}
c[ nt + 1 ] = 1e18 ;
LL ans = 0 ; cnt = 0 ;
for ( int i = 0 , j = 0 ; i <= nt; i++ ) {
if ( c[ i] == c[ i + 1 ] ) continue ;
LL r = c[ i + 1 ] - 1 + d[ i] ;
while ( j < ns && f[ j + 1 ] <= r) ++ j;
for ( int k = cnt + 1 ; k <= i + j; k++ ) {
LL t = max ( f[ k - i] - d[ i] , c[ i] ) ;
ans = ( ans + t % MOD * k) % MOD;
}
cnt = i + j;
}
printf ( "%lld\n" , ans) ;
}
return 0 ;
}