博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[NOI2010]超级钢琴(RMQ+堆)
阅读量:4663 次
发布时间:2019-06-09

本文共 1243 字,大约阅读时间需要 4 分钟。

小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。

这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。

一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。

小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。

Solution

题目需要求一个数列的前k大的字段和。

因为字段的左右端点都是移动的,我们不能直接维护这么一个东西,更不能把所有合法子段都加入堆中贪心。

考虑固定一个端点。

对于一个固定的左端点,最优的右端点是确定的(可以用ST表O(1)找出来)。

所以我们把所有左端点都加入堆中,每次取出最大值后,将(l—pos-1)和(pos+1—r)加入堆(pos是上一次最优点)。

Code

#include
#include
#include
#include
#define N 500002using namespace std;typedef long long ll;ll sum[N],st[N][22],ans;int pos[N][22],n,k,l,r,ji[N];ll RMQ(int l,int r){ return max(st[l][ji[r-l+1]],st[r-(1<
q;int main(){ scanf("%d%d%d%d",&n,&k,&l,&r); for(int i=1;i<=n;++i){scanf("%lld",&sum[i]);sum[i]+=sum[i-1];st[i][0]=sum[i];pos[i][0]=i;} for(int i=1;i<=n;++i)ji[i]=log(i)/log(2); for(int i=1;(1<
<=n;++i) for(int j=1;j<=n;++j){ st[j][i]=st[j][i-1];pos[j][i]=pos[j][i-1]; if(j+(1<
<=n&&st[j+(1<
st[j][i]){ st[j][i]=st[j+(1<
sum[po])po=pos[x.r-(1<

 

转载于:https://www.cnblogs.com/ZH-comld/p/9544595.html

你可能感兴趣的文章
nodejs网页请求data事件返回字符串
查看>>
keil uvision4不能显示中文
查看>>
SubSonic3.0使用外连接查询时查询不出数据的问题修改
查看>>
spring MVC 入门:
查看>>
【转】Java 面试题问与答:编译时与运行时
查看>>
windows启动过程
查看>>
刷面经笔记2019.02.14
查看>>
C# string.Format 与+性能比较
查看>>
设计模式培训之二:简单工厂、工厂方法
查看>>
C语言正整数除法向上取整
查看>>
酒店之王——网络流——dinic
查看>>
Windows7单机部署Hbase
查看>>
理解iOS Event Handling
查看>>
CreateCompatibleDC与BitBlt 学习
查看>>
十、HQL查询
查看>>
主要的调用约定关键字
查看>>
出队列操作
查看>>
提交表单时为了防止重复提交的进度条
查看>>
对于保证浮点数计算的正确性,有两种常见方式
查看>>
描述用浏览器访问 www.baidu.com 的过程
查看>>