虽然说是常见模型,但是这里只有一种模型,表示比较弱,只会一种模型。
先来一道超简单的例题:P1631 序列合并
亲
测
,
输
入
数
据
按
从
小
到
大
排
列
(
不
要
问
我
是
怎
么
知
道
的
)
\color{red}{亲测,输入数据按从小到大排列(不要问我是怎么知道的)}
亲测,输入数据按从小到大排列(不要问我是怎么知道的)
要把所有和的值都拿来放进堆里绝对超时了(On都过不了),这种时候堆就起到了它的作用。因为我们发现我们只用求前k大的和,那么剩下有 n ∗ ( n − 1 ) n*(n-1) n∗(n−1)的和都是毫无意义的。所以我们会有一个想法,如果对于一个元素,如果在堆中肯定有一个比它小的元素,那我们不需要把这个元素插入堆中,直到肯定比它小的这个数弹出,再把这个元素插入堆中。正确性显而易见:就算这个元素在堆中,肯定比它小的元素弹出之前这个元素是不会弹出的,所以不如干脆在肯定比它小的元素弹出之前就不把它插入堆中。
最后我们得到了这道题的算法:
1.先排序,将 a 1 + b 1 a_1+b_1 a1+b1插入堆。
2.每次弹出,假设弹出 a i + b j a_i+b_j ai+bj,就插入 a i + 1 + b j + 1 a_{i+1}+b_{j+1} ai+1+bj+1。
由于排序复杂度和堆操作复杂度均为 n l o g n nlogn nlogn,总复杂度就是 n l o g n nlogn nlogn的。
于是我们就得到了堆的模型:
1.对于一些元素求前
k
k
k个(第
k
k
k个)
2.可以快速判断前
m
m
m小(大)的元素,
m
m
m应该比较小,起码小于
n
n
n。
3.在弹出一个元素后,可以快速求出可能成为最大值的
r
r
r个元素。
r
r
r要比较小。
4.保证复杂度
(
m
+
k
∗
r
)
l
o
g
(
m
+
k
∗
r
)
(m+k*r)log(m+k*r)
(m+k∗r)log(m+k∗r)可过
下面我们来试一试水:2006: [NOI2010]超级钢琴
#2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MB
Submit: 3634 Solved: 1803
[Submit][Status][Discuss]
##Description
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的
音乐。 这架超级钢琴可以弹奏出
n
n
n个音符,编号为1至
n
n
n。第
i
i
i个音符的美妙度为
A
i
A_i
Ai,其中
A
i
A_i
Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于
L
L
L且不多于
R
R
R。我们定义超级和弦的美妙度为其包含的
所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由
k
k
k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由
k
k
k个不同的超级和弦组成。
我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
大值是多少。
##Input
第一行包含四个正整数
n
,
k
,
L
,
R
n, k, L, R
n,k,L,R。其中
n
n
n为音符的个数,
k
k
k为乐曲所包含的超级和弦个数,
L
L
L和
R
R
R分别是超级和弦所
包含音符个数的下限和上限。 接下来
n
n
n行,每行包含一个整数
A
i
A_i
Ai,表示按编号从小到大每个音符的美妙度。
N
≤
500
,
000
N\leq 500,000
N≤500,000
k
≤
500
,
000
k\leq 500,000
k≤500,000
−
1000
≤
A
i
≤
1000
,
1
≤
L
≤
R
≤
N
-1000\leq A_i\leq1000,1\leq L\leq R\leq N
−1000≤Ai≤1000,1≤L≤R≤N且保证一定存在满足条件的乐曲
##Output
只有一个整数,表示乐曲美妙度的最大值。
####Sample Input
4 3 2 3
3
2
-6
8
####Sample Output
11
##样例说明
共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。
啪!刚做完普及组的题,你就给我看这个???
不过相信以你的智商这道题分分钟口胡对不对?(因为代码我也没打,还是口胡吧)
首先让我们看一看上面的几个条件:
1.肯定是满足的
2和3可能需要思考一下。
2.首先我们用 f i , L , R f_{i,L,R} fi,L,R表示以 i i i为起点,长度在L和R之间的和弦的最大值。首先预处理所有 f i , L , R f_{i,L,R} fi,L,R。这一定是最大的前 n n n个。条件2满足了。
3.当弹出了 f i , L , R f_{i,L,R} fi,L,R后,假设,最长为 [ i , p ] [i,p] [i,p],就插入 f i , L , p − 1 f_{i,L,p-1} fi,L,p−1和 f i , p + 1 , R f_{i,p+1,R} fi,p+1,R。条件3满足。
4.由上知, m = n , r = 2 m=n,r=2 m=n,r=2,是可以过的。
但是最后还有一个问题:求 f i , L , R f_{i,L,R} fi,L,R。
这个是比较简单的,st表和线段树都可以实现,求数列的前缀和,然后 p = m a x { i + L − 1 , i + R − 1 } p=max\{i+L-1,i+R-1\} p=max{i+L−1,i+R−1}对吧。
恭喜你noi AC一题。
有兴趣可以看一看这道题:bzoj4504: K个串