Description

小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。

Input

第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。

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。

HINT

N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

题意:求前K大的连续区间和的和。

思路:之前遇到过,和堆有关,但是当时太弱,没敢做。所以回来参考了一下别人的代码,学习一下发现也没那么难。

(前辈已经写得很清楚了,我就不重复了。如下:

【转】一类经典的问题:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5783868.html

我们发现,固定左端点ii,能够得到长度满足条件的右端点区间

那么我们定义一个五元组(i,L,R,val,pos),其中,ii表示固定下的左端点,L,R表示右端点存在的区间,val表示右端点存在在这个区间的时候最大的价值,pos表示右端点此时的位置

那么我把这个五元组放到堆中,每次取出val最大的,把这个区间裂解,得到的符合条件的两个新的五元组再加入新的区间

具体就是(i,L,R,val,pos)−−>(i,L,pos−1,val′,pos′)+(i,pos+1,R,val′′,pos′′)

至于如何求val和pos,用ST表记录一下前缀和就可以了。

(自己写起来感觉还是蛮简单的。

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
struct in{
int i,L,R,val,pos;
in(){}
in(int ii,int LL,int RR,int vv,int pp):i(ii),L(LL),R(RR),val(vv),pos(pp){}
bool operator<(const in &a) const{ return val<a.val; }
};
priority_queue<in>q;
int dp[maxn][],pos[maxn][];long long ans;
int getmax(int L,int R) //区间最大的位置
{
int t=log2(R-L+);
if(dp[L][t]>dp[R-(<<t)+][t]) return pos[L][t];
return pos[R-(<<t)+][t];
}
int main()
{
int N,K,LL,RR,i,j;
scanf("%d%d%d%d",&N,&K,&LL,&RR);
for(i=;i<=N;i++) scanf("%d",&dp[i][]);
for(i=;i<=N;i++) dp[i][]+=dp[i-][],pos[i][]=i;
for(i=;i<=;i++) //ST表 。
for(j=;j+(<<i)-<=N;j++){
if(dp[j][i-]>dp[j+(<<(i-))][i-]) dp[j][i]=dp[j][i-],pos[j][i]=pos[j][i-];
else dp[j][i]=dp[j+(<<(i-))][i-],pos[j][i]=pos[j+(<<(i-))][i-];
}
for(i=;i+LL-<=N;i++){ //最开始最大个N个数。
int p=getmax(i+LL-,min(N,i+RR-));
q.push(in(i,i+LL-,min(N,i+RR-),dp[p][]-dp[i-][],p));
}
while(K&&!q.empty()){
in now=q.top(); q.pop();
ans+=now.val;
if(now.L<now.pos) {
int p=getmax(now.L,now.pos-);
q.push(in(now.i,now.L,now.pos-,dp[p][]-dp[now.i-][],p));
}
if(now.R>now.pos){
int p=getmax(now.pos+,now.R);
q.push(in(now.i,now.pos+,now.R,dp[p][]-dp[now.i-][],p));
}
K--;
}
printf("%lld\n",ans);
return ;
}

最新文章

  1. 运用TensorFlow处理简单的NLP问题
  2. html 生成pdf
  3. MATLAB plot 绘图的一些经验,记下来,facilitate future work
  4. 在chrome 总调试cordova出现Detached from the target. Remote debugging has been terminated with reason: Connection lost. Please re-attach to the new target
  5. 设置ArcGIS的外观改回到出厂
  6. NYOJ-79 拦截导弹 AC 分类: NYOJ 2014-01-01 23:25 167人阅读 评论(0) 收藏
  7. C#用xpath查找某节点
  8. 获取fragment中的控件的写法
  9. 【HDOJ】1053 Entropy
  10. 用java具体代码实现分数(即有理数)四则运算
  11. iOS开发:深入理解GCD 第一篇
  12. Java8:使用Lambda表达式增强版Comparator排序
  13. AmpLab Tachyon and Shark update
  14. BZOJ 4553 Tjoi2016&amp;Heoi2016 序列
  15. 深入剖析Java编程中的中文问题及建议最优解决方法
  16. H5 31-CSS元素显示模式转换
  17. controller修改response返回值
  18. python 获取前一天或前N天的日期
  19. Estimation And Gain
  20. thick置备和 thin置备,克隆,模板和快照

热门文章

  1. mac下报错 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
  2. C# 将链表存入二进制文件及读取二进制文件得到链表示例
  3. 使用 rman duplicate from active database 搭建dataguard 手记--系列二
  4. 【windows socket+UDPserverclient】
  5. 关于C++ 命名空间Namespace 的解析
  6. C语言-回溯例3
  7. cocos2d-x项目101次相遇:在HelloWorld上--建立新场景
  8. Java IO 类
  9. 改动UITextfield的Placeholder字体的颜色
  10. EasyRTMP实现Demux解析MP4文件进行rtmp推送实现RTMP直播功能