BZOJ 2006: [NOI2010]超级钢琴
2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MB
Submit: 2613 Solved: 1297
[Submit][Status][Discuss]
Description
Input
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
学习的题解,转载在下——
堆+RMQ
定义一个四元组(i,l,r,t)表示是以第i个为开头的,结尾在l-r之间(满足长度>=L,<=R),且结尾在t的权值和最大。
首先把以每一位开头的四元组加入堆,此时的l,r是恰好满足长度>=L,<=R;
堆中排序的关键字是权值之和。
然后把堆顶取出(i,l,r,t),然后再把(i,l,t-1,t')和(i,t+1,r,t'')加入堆中(因为要满足任意两个序列不同的条件)
那么四元组中的t如何快速求出?
用RMQ即可:维护前缀和,权值和就是sum[t]-sum[i-1],对于用一个四元组sum[i-1]相同,因此只要找到l-r中sum[i]最大的即可。
#include <queue>
#include <cstdio> inline int nextChar(void)
{
const static int siz = ; static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz; if (hd == tl)
fread(hd = buf, , siz, stdin); return *hd++;
} inline int nextInt(void)
{
register int ret = ;
register int neg = false;
register int bit = nextChar(); for (; bit < ; bit = nextChar())
if (bit == '-')neg ^= true; for (; bit > ; bit = nextChar())
ret = ret * + bit - ; return neg ? -ret : ret;
} const int siz = ; int N, M, L, R; int num[siz];
int sum[siz]; int st[siz][], log[siz]; inline void preworkRMQ(void)
{
for (int i = ; i <= N; ++i)
st[i][] = i; for (int i = ; ( << i) <= N; ++i)
for (int j = ; j + ( << i) - <= N; ++j)
{
int x = st[j][i - ];
int y = st[j + ( << (i - ))][i - ];
st[j][i] = sum[x] > sum[y] ? x : y;
} log[] = -; for (int i = ; i <= N; ++i)
log[i] = log[i >> ] + ;
} inline int query(int l, int r)
{
if (l == r)
return l; int t = log[r - l + ]; int x = st[l][t];
int y = st[r - ( << t) + ][t]; return sum[x] > sum[y] ? x : y;
} struct data
{
int p, t, l, r; data(void) {};
data(int a, int b, int c, int d) :
p(a), t(b), l(c), r(d) {};
}; inline bool operator < (const data &a, const data &b)
{
return sum[a.t] - sum[a.p - ] < sum[b.t] - sum[b.p - ];
} std::priority_queue<data> h; signed main(void)
{
N = nextInt();
M = nextInt();
L = nextInt();
R = nextInt(); for (int i = ; i <= N; ++i)
num[i] = nextInt(); for (int i = ; i <= N; ++i)
sum[i] = sum[i - ] + num[i]; preworkRMQ(); long long ans = ; for (int i = ; i <= N - L + ; ++i)
{
int l = i + L - ;
int r = i + R - ; if (r > N)
r = N; h.push(data(i, query(l, r), l, r));
} for (int i = ; i <= M; ++i)
{
data top = h.top(); h.pop(); ans += sum[top.t] - sum[top.p - ]; if (top.t > top.l)
h.push(data(top.p, query(top.l, top.t - ), top.l, top.t - ));
if (top.t < top.r)
h.push(data(top.p, query(top.t + , top.r), top.t + , top.r));
} printf("%lld\n", ans);
}
@Author: YouSiki
BZOJ 2006: [NOI2010]超级钢琴的更多相关文章
- Bzoj 2006: [NOI2010]超级钢琴 堆,ST表
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2222 Solved: 1082[Submit][Statu ...
- BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )
取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<c ...
- 洛谷 P2048 BZOJ 2006 [NOI2010]超级钢琴
题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中A ...
- BZOJ.2006.[NOI2010]超级钢琴(贪心 堆)
BZOJ 洛谷 思路和BZOJ3784一样,用前缀和+堆维护.做那题吧,不赘述啦. (没错我就是水一个AC) //54620kb 1060ms #include <queue> #incl ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006 [NOI2010]超级钢琴 (堆+主席树)
题面:BZOJ传送门 洛谷传送门 让你求前$K$大的子序列和,$n\leq 5*10^{5}$ 只想到了个$nlog^{2}n$的做法,似乎要被卡常就看题解了.. 好神奇的操作啊,我傻了 我们把序列和 ...
- BZOJ 2006 NOI2010 超级钢琴 划分树+堆
题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- bzoj 2006: [NOI2010]超级钢琴【st表+堆】
设计一个五元组(i,l,r,p,v),表示在以i为左端点,右端点落在(l,r)中的情况下,取最大值v时右端点落在p.把这个五元组塞到优先队列里,以v排序,每次取出一个,然后把这个取过的五元组分成两个( ...
随机推荐
- 单台机器配置redis多实例
1.增加/usr/local/redis/etc中拷贝一份配置文件重新命名为redis6483.conf 2.编辑redis6483.conf daemonize yes //以后台进程启动 pid ...
- jvm内存溢出分析
概述 jvm中除了程序计数器,其他的区域都有可能会发生内存溢出 内存溢出是什么? 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出 内存溢出和 ...
- 【前端优化之渲染优化】大屏android手机动画丢帧的背后
前言 上周我与阿里的宇果有一次技术的交流,然后对天猫H5站点做了一些浅层次的分析,后面点时间基本天天都会有联系,中途聊了一些技术细节.聊了双方团队在干什么,最后聊到了前端优化.因为我本身参与了几次携程 ...
- OC多态
要点: 1.多种形态,引用的多种形态对于一个引用变量,可以指向任何类的对象.对于一个父类的引用(类与类之间有一种继承关系),可以指向子类,也可以指向本类,指向的类型不同.当通过此引用向对象发送消息,调 ...
- Android中通信协议
一.TCP/IP协议(传输层协议) 1.Socket与ServerSocket Socket是应用层与TCP/IP协议簇通讯的中间抽象层,Socket是一组接口,在设计模式中,Socket的设计就是门 ...
- (七)Maven使用的最佳实践
这里说一下在使用Maven过程中不是必须的,但十分有用的几个实践,关键时刻或许能解决您的问题. 1.设置MAVEN_OPTS环境变量 通常需要设置MAVEN_OPTS的值为-Xms128m -Xmx5 ...
- 用gcc进行程序的编译
在Linux系统上,一个档案能不能被执行看的是有没有可执行的那个权限(x),不过,Linux系统上真正认识的可执行文件其实是二进制文件(binary program),例如/usr/bin/passw ...
- SQL删除语句同时向备份表插入数据
从这里摘抄下来的,觉得很不错,http://www.cnblogs.com/ljhdo/p/5792886.html#3503524 ,以后就用这种方式删除,再也不用担心删除错数据啦!!!
- (四)Spark集群搭建-Java&Python版Spark
Spark集群搭建 视频教程 1.优酷 2.YouTube 安装scala环境 下载地址http://www.scala-lang.org/download/ 上传scala-2.10.5.tgz到m ...
- 机器学习实战笔记(Python实现)-03-朴素贝叶斯
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...