【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MB
Submit: 2473 Solved: 1211
[Submit][Status][Discuss]
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
3
2
-6
8
Sample Output
【样例说明】
共有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
Source
Solution
一类经典的问题
暴力的思路,枚举出每个长度在$[l,r]$的区间,然后排序计算答案
我们发现,固定左端点$i$,能够得到长度满足条件的右端点区间
那么我们定义一个五元祖$(i,L,R,val,pos)$,其中,$i$表示固定下的左端点,$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表记录一下前缀和就可以了
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 500010
int N,K,L,R,A[MAXN],SA[MAXN];
long long ans;
struct HeapNode
{
int i,L,R,val,pos;
bool operator < (const HeapNode & A) const
{return val<A.val;}
};
inline int Max(int x,int y) {return SA[x]>SA[y]? x:y;}
int log2[MAXN],dp[][MAXN];
void ST()
{
log2[]=-;
for (int i=; i<=N; i++)
if (i&(i-)) log2[i]=log2[i-]; else log2[i]=log2[i-]+;
for (int i=; i<=N; i++) dp[][i]=i;
for (int j=; (<<j)<=N; j++)
for (int i=; i+(<<j)-<=N; i++)
dp[j][i]=Max(dp[j-][i],dp[j-][i+(<<j-)]);
}
inline int RMQ(int l,int r)
{
int tmp=log2[r-l+];
return Max(dp[tmp][l],dp[tmp][r-(<<tmp)+]);
}
priority_queue<HeapNode>heap;
int main()
{
N=read(); K=read(); L=read(); R=read();
for (int i=; i<=N; i++) A[i]=read(),SA[i]=SA[i-]+A[i];
ST();
for (int i=; i<=N; i++)
if (i+L-<=N)
{
int ls=i+L-,rs=min(i+R-,N),pos=RMQ(ls,rs),val=SA[pos]-SA[i-];
heap.push( (HeapNode){i,ls,rs,val,pos} );
}
else break;
while (!heap.empty() && K)
{
HeapNode now=heap.top(); heap.pop();
ans+=now.val; K--;
HeapNode ls=now,rs=now;
ls.R=now.pos-;
if (ls.R>=ls.L)
ls.pos=RMQ(ls.L,ls.R),ls.val=SA[ls.pos]-SA[ls.i-],heap.push(ls);
rs.L=now.pos+;
if (rs.R>=rs.L)
rs.pos=RMQ(rs.L,rs.R),rs.val=SA[rs.pos]-SA[rs.i-],heap.push(rs);
}
printf("%lld\n",ans);
return ;
}
自己这题的常数还是蛮小的..稍微改了一下就BZOJ rk4了..
看到这个题目还是蛮震撼的。。。自从钢琴10级之后,好久没认真练过了吧.....那可真蠢
【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)的更多相关文章
- bzoj 2006 超级钢琴 —— ST表
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 本来应该是可以用主席树,找区间最小值,取出来后再找那段区间的次小值...... 但也可 ...
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
[BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...
- BZOJ 2006 超级钢琴(堆+主席树)
很好的一道题. 题意:给出长度为n的数列,选择k个互不相同的区间,满足每个区间长度在[L,R]内,求所有选择的区间和的总和最大是多少.(n,k<=5e5). 首先将区间和转化为前缀和之差,那么我 ...
- BZOJ 2006 超级钢琴(划分树+优先队列)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2006 题意: 给出一个数列A,L,R,构造出一个新的集合,集合中的数字为A中任意连续t( ...
- [BZOJ 2006] 超级钢琴
Link: https://www.lydsy.com/JudgeOnline/problem.php?id=2006 Algorithm: 对于此类区间最值类问题,我们可以通过控制一端不变来寻找当前 ...
随机推荐
- IntelliJ IDEA运行tomcat项目编码错误, 及如何指定tomcat编码
刚开始用IDEA, 在跑dubbo开发时, 发现一个很奇怪的问题, 远程调用服务端的方法时, 传入的中文参数会变成GBK编码. 经过好长时间的跟踪终于把问题定位到了IDEA里配置的Tomcat. 凡是 ...
- Tomcat 5.5启动需要用户名密码的解决方案
我在使用Tomcat的时候碰到这样的问题,然后在csdn里面找到方法,然后保存一份,原帖地址:Tomcat用户名密码,8#原来的tomcat-user.xml是 <?xml version=& ...
- JavaScript继承与原型链
对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念( ES6 新增了c ...
- 李学斌:论复杂系统中的应用间协作V3
说明 本文主要讨论了巨型复杂业务系统的一种构建思路,力图实现决策意志的快速.准确.一致的下传并简化实施成本提供实施效率.通过全业务领域的即时流程编排,实现全网业务IT系统的快速建设与迭代.本文所讲的方 ...
- java:hibernate + oracle之坑爹的clob
oracle + hibernate 环境,如果表中有 clob字段,hibernate的Entity类,如果Column注解打在私有成员上,则clob私有成员,首字母一定要按字母顺序排在最后,安全的 ...
- Hibernate大福利 下载链接
正在学马士兵Hibernate的同学来看这里,这里提供了他视频里需要的JAR包,请尽情下载,给好评喔. 一.Hibernate 3.3.2 核心JAR包 http://pan.baidu.com/s/ ...
- 漫谈 Java 实例化类
Java 中实例化类的动作,你是否还是一成不变 new 对应对象呢? 经手的项目多了,代码编写量自然会增加,渐渐的会对设计模式产生感觉. 怎样使书写出来的类实例化动作,高内聚,低耦合,又兼具一定的扩展 ...
- opencv4-highgui之视频的输入和输出以及滚动条
这是<opencv2.4.9tutorial.pdf>的highgui的三个例子.通过简短的介绍来实现不同函数的理解,省去一些不需要说的东西. 一.增加滑动条 这是opencv中为数不多的 ...
- 我开源了一个ios应用,你们拿去随便玩
今天开源一个ios应用,自己写的,你们拿去随便玩.地址是: https://github.com/huijimuhe/prankPro 光拿来玩不理清个来龙去脉玩的也不开心是吧,那我就给你们摆摆来龙去 ...
- Nodejs进阶:如何玩转子进程(child_process)
本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 在node中,child_process这个模 ...