2006: [NOI2010]超级钢琴

Time Limit: 20 Sec  Memory Limit: 552 MB

Submit: 3446  Solved: 1692

[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,表示按编号从小到大每个音符的美妙度。
N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

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。

我们利用前缀和可以很快得到最大的答案

对于每个点i,我们只要求出sum[i + L - 1] 到 sum[i + R - 1]中最大的值就可以得到以i为左端点的最大值

我们设这样一个值为三元组(i,l,r)的值,表示以i开头右端点在[l,r]内的区间最大和

利用这个,我们求出最大值后,求第二大的值可能以其它i开头,也可能仍然以当前i开头,我们就把当前(i,l,r)分裂成

(i,l,t - 1)和(i,t + 1,r)就可以了

重复K次,即得结果

但是如何做到快速求区间最大值呢?

这就用到了RMQ算法【ST表】

ST表是用以解决区间最大值无修改的算法,预处理O(nlogn),查询O(1)

可以说在没有修改的情况下比线段树优很多

具体实现:

预处理

我们设mx[i][j]表示以[i,i + 2^j - 1],也就是以i开头长度为2^j的区间的最大值

利用倍增的方法,mx[i][j] = max(mx[i][j - 1],mx[i + 2^(j - 1)][j - 1]);

我们可以处理出所有的mx【但是要注意数组不要越界】

查询

我们要查询的区间长度是2的n次方很好办,就是mx[i][n]
但是如果不是呢?
我们可以把原区间分成两个相交的2^n的区间,求二者的最大值即可
具体区间为[l,r],我们令t = log2(r - l + 1),则ans = max(mx[l][t],mx[r - 2^t + 1][t]);

最后我们就可以A啦
【STL似乎不会T】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define mp(a,b,c,d) (node){a,b,c,d}
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N,K,L,R,sum[maxn],mx[maxn][30],Log[maxn];
LL ans = 0;
struct node{int i,l,r,t;};
inline bool operator <(const node& a,const node& b){return sum[a.t] - sum[a.i - 1] < sum[b.t] - sum[b.i - 1];}
priority_queue<node,vector<node> > q;
void RMQ(){
Log[0] = -1;
for (int i = 1; i <= N; i++) Log[i] = Log[i >> 1] + 1;
int t = Log[N];
REP(i,N) mx[i][0] = i;
for (int i = N; i; i--){
for (int j = 1; j <= t; j++){
if (i + (1 << j) - 1 > N) break;
int t1 = mx[i][j - 1],t2 = mx[i + (1 << j - 1)][j - 1];
mx[i][j] = sum[t1] > sum[t2] ? t1 : t2;
}
}
}
inline int Query(int l,int r){
if (l == r) return l;
int t = Log[r - l + 1],t1 = mx[l][t],t2 = mx[r - (1 << t) + 1][t];
return sum[t1] > sum[t2] ? t1 : t2;
}
void solve(){
node u;
REP(i,N){
if (i + L - 1 > N) break;
int r = min(i + R - 1,N);
q.push(mp(i,i + L - 1,r,Query(i + L - 1,r)));
}
for (int i = 1; i <= K; i++){
u = q.top(); q.pop();
ans += sum[u.t] - sum[u.i - 1];
if (u.t - 1 >= u.l) q.push(mp(u.i,u.l,u.t - 1,Query(u.l,u.t - 1)));
if (u.t + 1 <= u.r) q.push(mp(u.i,u.t + 1,u.r,Query(u.t + 1,u.r)));
}
}
int main(){
N = RD(); K = RD(); L = RD(); R = RD();
REP(i,N) sum[i] = sum[i - 1] + RD();
RMQ();
solve();
cout<<ans<<endl;
return 0;
}

BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】的更多相关文章

  1. BZOJ2006[NOI2010]超级钢琴——堆+主席树

    题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...

  2. bzoj2006 [NOI2010]超级钢琴 (及其拓展)

    bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...

  3. P2048 [NOI2010]超级钢琴(RMQ+堆+贪心)

    P2048 [NOI2010]超级钢琴 区间和--->前缀和做差 多次查询区间和最大--->前缀和RMQ 每次取出最大的区间和--->堆 于是我们设个3元组$(o,l,r)$,表示左 ...

  4. [BZOJ2006][NOI2010]超级钢琴(ST表+堆)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3679  Solved: 1828[Submit][Statu ...

  5. bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴

    http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...

  6. 【BZOJ 2006】2006: [NOI2010]超级钢琴(RMQ+优先队列)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2792  Solved: 1388 Description 小 ...

  7. Bzoj 2006: [NOI2010]超级钢琴 堆,ST表

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2222  Solved: 1082[Submit][Statu ...

  8. [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 3591  Solved: 1780[Submit][Statu ...

  9. [NOI2010]超级钢琴(RMQ+堆)

    小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负 ...

随机推荐

  1. C++ 基础面试题-1

    请说出下面代码在32位系统下的输出内容 /* ** 2018/03/21 21:43:00 ** Brief: ** Author:ZhangJianWei ** Email:Dream_Dog@16 ...

  2. adb获取设备的序列号

    用数据线连接手机, 打开开发者模式, 并赋予相关权限, 在CMD命令行输入: adb devices 第一个参数即为设备的序列号, 第二个参数device表示设备的状态是在线.

  3. jmeter基础之录制篇

    一.前言 jmeter如今被越来越多人喜爱的一款测试工具,相比于loadrunner它体积特轻便.jmeter不仅用来做单接口测试,压测还能做性能,主要是一款开源的,可以写一个你需要的插件功能再添加里 ...

  4. Linux命令应用大词典-第30章 审计系统

    30.1 auditctl:控制内核的审计系统 30.2 aureport:生成审计信息报表 30.3 ausearch:搜索审计记录 30.4 autrace:跟踪指定进程 30.5 audit-v ...

  5. TPO-14 C2 Prepare for a career in journalism

    TPO-14 C2 Prepare for a career in journalism 第 1 段 1.Listen to a conversation between a student and ...

  6. 【system.folder】使用说明

    对象:system.folder 说明:提供一系列针对文件夹的操作 目录: 方法 返回 说明 system.folder.exists(folderPath) [True | False] 检测指定文 ...

  7. jdbc连接sql server2017进行简单的增、删、改、查操作

    这几天刚做完数据库的课程设计,来稍微总结一下如何通过jdbc访问sql server数据库进行简单的增删改查操作.在连接之前,需要简单地配置一下,包括下载对应jdk版本的驱动,设置环境变量等等.相关配 ...

  8. spark集群安装部署

    通过Ambari(HDP)或者Cloudera Management (CDH)等集群管理服务安装和部署在此不多介绍,只需要在界面直接操作和配置即可,本文主要通过原生安装,熟悉安装配置流程. 1.选取 ...

  9. XX出行项目子系统-统计系统设计(定时器项目设计例子)

    一. 引言 目前开发的XX出行系统,需要开发数据统计功能,鉴于约约出行系统已经在运营,并且有新版本的迭代,方便以后下个版本复用,遂新建一个子系统. 二. 架构设计 三. 具体实现 1.MySql数据库 ...

  10. 技能get,React的优雅升级!

    今日,我们不啖鸡汤,不饮鸡血 只有干货——关于React的优雅升级 双手奉上,来,干了! -2019年第4期- 夫 子 说 本次升级基础包情况:react 15.6 -> 16.6 升级流程: ...