洛谷 P2048 BZOJ 2006 [NOI2010]超级钢琴
题目描述
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。
这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。
一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。
输入输出格式
输入格式:
输入第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所包含音符个数的下限和上限。
接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
输出格式:
输出只有一个整数,表示乐曲美妙度的最大值。
输入输出样例
输入样例#1:
4 3 2 3
3
2
-6
8
输出样例#1:
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。
题解
堆+st表
我们定义一个三元组\((s, l, r)\) 表示以s为左端点 右端点在\(l-r\)这段区间内区间和最大
维护一个前缀和
贪心地想,既然\(s\)已经固定那么对于右端点在\(l-r\)这段区间内,我们要取前缀和最大的那个值,st搞一下就好了
定义\(t\)为\(l-r\)区间前缀和最大的位置
我们维护一个堆
每次取出价值最大
然后把\((s, l, t-1) (s, t+1, r)\)放进去
注意特判一下\(l=t, r=t\)的情况
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
inline int gi() {
int f = 1, s = 0;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -1, c = getchar();
while (c >= '0' && c <= '9') s = s*10+c-'0', c = getchar();
return f == 1 ? s : -s;
}
const int N = 500010;
int mx[N][21], a[N], n, k, L, R;
LL sum[N];
void init() {
for (int i = 1; i <= n; i++)
mx[i][0] = i;
for (int i = 1; (1<<i) <= n; i++)
for (int j = 1; j + (1<<i) - 1 <= n; j++) {
int x = mx[j][i-1], y = mx[j+(1<<(i-1))][i-1];
mx[j][i] = sum[x] > sum[y] ? x : y;
}
return ;
}
inline int getmax(int l, int r) {
int k = log2(r-l+1), x = mx[l][k], y = mx[r-(1<<k)+1][k];
return sum[x] > sum[y] ? x : y;
}
struct node {
int s, l, r, t;
bool operator <(node z) const {
return (sum[t]-sum[s-1]) < (sum[z.t]-sum[z.s-1]);
}
};
priority_queue<node> q;
int main() {
n = gi(), k = gi(), L = gi(), R = gi();
for (int i = 1; i <= n; i++) {
a[i] = gi();
sum[i] = sum[i-1]+a[i];
}
init();
for (int i = 1; i+L-1 <= n; i++)
q.push((node) {i, i+L-1, min(n, i+R-1), getmax(i+L-1, min(n, i+R-1))});
LL ans = 0;
for (int i = 1; i <= k; i++) {
int l = q.top().l, r = q.top().r, s = q.top().s, t = q.top().t;
q.pop();
ans += sum[t]-sum[s-1];
if (t != l)
q.push((node) {s, l, t-1, getmax(l, t-1)});
if (t != r)
q.push((node) {s, t+1, r, getmax(t+1, r)});
}
printf("%lld\n", ans);
return 0;
}
洛谷 P2048 BZOJ 2006 [NOI2010]超级钢琴的更多相关文章
- 洛谷 2048 BZOJ 2006 [NOI2010]超级钢琴
[题解] 贪心题.设五元组(mx,pos,l,r1,r2)表示最大值为mx,取得最大值的区间右端点为pos,区间左端点为l,区间右端点的可选区间为[r1,r2]. 每次从堆里拎出最大值,然后把这个区间 ...
- BZOJ 2006: [NOI2010]超级钢琴
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2613 Solved: 1297[Submit][Statu ...
- 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 ...
- BZOJ.2006.[NOI2010]超级钢琴(贪心 堆)
BZOJ 洛谷 思路和BZOJ3784一样,用前缀和+堆维护.做那题吧,不赘述啦. (没错我就是水一个AC) //54620kb 1060ms #include <queue> #incl ...
- BZOJ 2006 [NOI2010]超级钢琴 (堆+主席树)
题面:BZOJ传送门 洛谷传送门 让你求前$K$大的子序列和,$n\leq 5*10^{5}$ 只想到了个$nlog^{2}n$的做法,似乎要被卡常就看题解了.. 好神奇的操作啊,我傻了 我们把序列和 ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006 NOI2010 超级钢琴 划分树+堆
题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
随机推荐
- Entity Framework在不同数据库下的配置
http://blog.csdn.net/weiky626/article/details/17068593 http://blog.csdn.net/niewq/article/details/41 ...
- input 框提示信息
给input添加提示信息,只需添加 “placeholder”的class,将提示信息放在value中, 其中“placeholder”的名字是随便取的,不是H5的“placeholder”属性 例子 ...
- (转)第一次发博客-说说我的B/S开发框架(asp.net mvc + web api + easyui)
原文地址:http://www.cnblogs.com/xqin/archive/2013/05/29/3105291.html 前言 这些年一直在.net下做企业web系统开发,前前后后经历的不同的 ...
- txt文本怎么去除重复项
txt文本怎么去除重复项?做网络推广的朋友经常会遇到这样的问题,txt文本文件里面有许多人名或者电话号码用来发送邮件或者短信,通常有许多是重复的,下面我来介绍两个方法来去除重复项,以人名为范本讲解. ...
- 简单接触oracle数据库nvl函数decode函数
SQL语句的DECODE()和NVL()函数用法 SELECT DECODE(choose_tool,0,'宝马',1,'电动车',2,'自行车','步行') AS my_tool FROM dat ...
- 执行存储过程比即时SQL执行慢的解决方案
发生过这样一件事, 写了一个SQL,查询数据大概5秒,但是放到存储过程里面去了过后,查了5分钟也没给出结果,后来网上找解决方案,终于找到一个解决方案. 在存储过程的参数那里对参数进行一个传递.反正他们 ...
- 微信Token验证
/// <summary> /// 微信验证 /// </summary> /// <param name="echostr"></par ...
- tomcat 安装与使用!
$安装:安装方式为zip解压. 打开tomcat官网点此链接:https://tomcat.apache.org/download-80.cgi 选择你想要使用的版本,点击相应位数选择zip解压包版, ...
- 分享一个利用HTML5制作的海浪效果代码
在前面简单讲述了一下HTML里的Canvas,这次根据Canvas完成了“海浪效果”(水波上升). (O(∩_∩)O哈哈哈~作者我能看这个动画看一下午) 上升水波.gif 动画分析构成:贝塞尔曲线画布 ...
- 如何设置linux支持上传的文件中文不乱吗
一.背景: 1.由于客户的需求,需要a链接打开的pdf文件,支持中文名称的 二.步骤 ①.查看当前编码 locale ②.编辑 vi /etc/profile 打开后结尾处添加 export LA ...