BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表

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


把所有的子串当成后缀的前缀来做。

那么对于从i这个位置开始的子串,有一个可以选取末位置j的范围[i+L-1,i+R-1]。

假设最大的合法子串在j这个位置,那么次大值一定出现在[i+L-1,j-1]和[j+1,i+R-1]中。

于是有了这样的想法:用堆来维护四元组<i,p,l,r>表示从i到p的子段,选择的范围从l到r。

然后每次查询区间最大值用ST表做即可。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
#define N 500050
int n,a[N],s[N],K,L,R,f[N][21],Lg[N],g[N][21];
ll ans;
struct A {
int x,p,l,r;
A() {}
A(int x_,int p_,int l_,int r_) :
x(x_),p(p_),l(l_),r(r_) {}
};
bool operator < (const A &x,const A &y) {
return s[x.p]-s[x.x-1]<s[y.p]-s[y.x-1];
}
__gnu_pbds::priority_queue<A>q;
int get_max(int l,int r) {
int len=Lg[r-l+1];
return f[l][len]>f[r-(1<<len)+1][len]?g[l][len]:g[r-(1<<len)+1][len];
}
void solve() {
int i;
for(i=1;i<=n-L+1;i++) {
int t=get_max(i+L-1,min(n,i+R-1));
q.push(A(i,t,i+L-1,min(n,i+R-1)));
}
for(i=1;i<=K;i++) {
A t=q.top(); q.pop();
//printf("%d %d\n",t.x,t.p);
ans+=s[t.p]-s[t.x-1];
if(t.p>t.l) q.push(A(t.x,get_max(t.l,t.p-1),t.l,t.p-1));
if(t.p<t.r) q.push(A(t.x,get_max(t.p+1,t.r),t.p+1,t.r));
}
}
int main() {
scanf("%d%d%d%d",&n,&K,&L,&R);
int i,j;
Lg[0]=-1;
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
f[i][0]=s[i];
g[i][0]=i;
Lg[i]=Lg[i>>1]+1;
}
Lg[0]=0;
for(j=1;(1<<j)<=n;j++) {
for(i=1;i+(1<<j)-1<=n;i++) {
if(f[i][j-1]>f[i+(1<<j-1)][j-1]) {
f[i][j]=f[i][j-1];
g[i][j]=g[i][j-1];
}else {
f[i][j]=f[i+(1<<j-1)][j-1];
g[i][j]=g[i+(1<<j-1)][j-1];
}
}
}
solve();
printf("%lld\n",ans);
}

BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表的更多相关文章

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

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

  2. 【NOI2010】超级钢琴 题解(贪心+堆+ST表)

    题目链接 题目大意:求序列内长度在$[L,R]$范围内前$k$大子序列之和. ---------------------- 考略每个左端点$i$,合法的区间右端点在$[i+L,i+R]$内. 不妨暴力 ...

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

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

  4. [NOI2010] 超级钢琴 - 贪心,堆,ST表

    这也算是第K大问题的套路题了(虽然我一开始还想了个假算法),大体想法就是先弄出最优的一批解,然后每次从中提出一个最优解并转移到一个次优解,用优先队列维护这个过程即可. 类似的问题很多,放在序列上的,放 ...

  5. BZOJ 2006 NOI2010 超级钢琴 划分树+堆

    题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...

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

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

  7. [ST表/贪心] NOI2010 超级钢琴

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

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

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

  9. 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆

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

随机推荐

  1. IT轮子系列(四)——使用Jquery+formdata对象 上传 文件

    前言 在MVC 中文件的上传,一般都采用控件: <h2>IT轮子四——文件上传</h2> <div> <input type="file" ...

  2. c#调用野狗云 rest api

    野狗云就不多介绍了,这里主要是记录一下c#调用他们提供的rest api,把数据post到野狗云存储,直接上代码 static void Main(string[] args) { string st ...

  3. AVL树之 Java的实现

    AVL树的介绍 AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1:而右边的不 ...

  4. python的logging模块之读取yaml配置文件。

    python的logging模块是用来记录应用程序的日志的.关于logging模块的介绍,我这里不赘述,请参见其他资料.这里主要讲讲如何来读取yaml配置文件进行定制化的日志输出. python要读取 ...

  5. Scala编程入门---函数式编程之集合操作

    集合的函数式编程: 实战常用: //map案例实战:为List中的每个元素都添加一个前缀. List("leo","Jen","peter" ...

  6. HTTP协议简单记录

    http协议的格式 1. 首行 2. 头 3. 空行 4. 体 http请求头 #Referer 请求来自哪里,如果是在http://www.baidu.com上点击链接发出的请求,那么Referer ...

  7. JavaScript的数组知识案例之随机点名器

    本次分享JavaScript主要知识点涉及到for循环.if选择结构判断语句.数组的定义.定时器.清除定时器.日期对象的使用. 执行后效果图: 思路: 1.网页结构搭建: HTML 2.网页布局美化: ...

  8. react 高阶组件的 理解和应用

    高阶组件是什么东西 简单的理解是:一个包装了另一个基础组件的组件.(相对高阶组件来说,我习惯把被包装的组件称为基础组件) 注意:这里说的是包装,可以理解成包裹和组装: 具体的是高阶组件的两种形式吧: ...

  9. ubuntu宽带连接

    1.打开终端:    输入:sudo pppoeconf    根据提示输入宽带用户名和密码,若提示Plugin rp-pppoe.so loaded.则已连接成功.2.手动开启/断开连接:    p ...

  10. 什么是分布式锁及正确使用redis实现分布式锁

    分布式锁 分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性. 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁 ...