点此看题面

大致题意: 要你求出区间和前\(k\)大的区间的区间和之和,其中每个区间的大小在\(L\)与\(R\)之间。

堆+\(RMQ\)

这道题目,我们可以先对\(1\sim n\)中的每一个\(i\)假设它为左端点,求出区间\([i+L-1,min(i+R-1,n)]\)中的一个右端点\(s\),使得对于任意一个\(j∈[i+L-1,min(i+R-1,n)]\),满足\(\sum_{x=i}^s a[x]>=\sum_{y=i}^j a[y]\)(这可以直接对每个位置的前缀和求\(RMQ\))。

然后,将每个\([i+L-1,s]\)的区间和扔入一个中维护。

进一步思考

一起来观察一下下面这张图:

我们会发现,\([i+L-1,s-1]\)和\([s+1,min(i+R-1,n)]\)两个区间中也可能含有使答案区间和前\(k\)大的右端点,所以,对于一个答案,我们在将其统计之后,需要将它重新拆成两部分再分别扔回堆中,这样就能保证没有遗漏了。

代码

#include<bits/stdc++.h>
#define LL long long
#define N 500000
using namespace std;
int n,m,l,r,a[N+5],Log2[N+5];
LL sum[N+5];
struct RMQ//RMQ区间最值
{
LL Max,Maxer;//Max存储最大的数,Maxer存储最大的数的编号
bool operator < (const RMQ a) const//比较两个RMQ结构体的大小
{
return Max<a.Max;//比较最大的数的大小
}
}R[N+5][25];
struct key
{
LL x,y,s,val,pos;//x,y表示区间能选的范围,pos,s表示选择了的区间的范围,val表示这个选择了的区间的区间和
bool operator < (const key a) const//比较两个key结构体的大小
{
return val<a.val;//比较区间和的大小
}
};
priority_queue<key> h;//一个堆
inline char tc()
{
static char ff[100000],*A=ff,*B=ff;
return A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0;int f=1;char ch;
while(!isdigit(ch=tc())) if(ch=='-') f=-1;
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
x*=f;
}
inline void write(LL x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void Start()//预处理
{
for(register int j=1;j<=25;++j)//预处理出RMQ
for(register int i=1;i+(1<<(j-1))<=n;++i)
R[i][j]=max(R[i][j-1],R[i+(1<<(j-1))][j-1]);
for(register int i=2;i<=n;++i) Log2[i]=Log2[i>>1]+1;//预处理出Log2[],减少精度误差
}
inline int Maxer(int l,int r)//返回这段区间内能使区间和最大的位置
{
int k=Log2[r-l+1];//一个RMQ的过程
return max(R[l][k],R[r-(1<<k)+1][k]).Maxer;
}
int main()
{
register int i;
for(read(n),read(m),read(l),read(r),i=1;i<=n;++i) read(a[i]),R[R[i][0].Maxer=i][0].Max=sum[i]=sum[i-1]+a[i];
Start();
for(i=1;i<=n-l+1;++i) h.push((key){i+l-1,(i+r-1<n?i+r-1:n),Maxer(i+l-1,(i+r-1<n?i+r-1:n)),sum[Maxer(i+l-1,(i+r-1<n?i+r-1:n))]-sum[i-1],i});//先将每一个区间加入堆
LL ans=0;//ans统计答案
while(m--)
{
key k=h.top();
h.pop(),ans+=k.val;//更新ans
if(k.x!=k.s) h.push((key){k.x,k.s-1,Maxer(k.x,k.s-1),sum[Maxer(k.x,k.s-1)]-sum[k.pos-1],k.pos});//若左边还有区间,就将左边一部分重新扔入堆中
if(k.s!=k.y) h.push((key){k.s+1,k.y,Maxer(k.s+1,k.y),sum[Maxer(k.s+1,k.y)]-sum[k.pos-1],k.pos});//若右边还有区间,就将右边一部分重新扔入堆中
}
return write(ans),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. BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MB Submit: 3446  Solved: 1692 [Submit][Sta ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. [Django笔记] models 深入学习

    对着官方文档撸一遍,顺便做点笔记 models 定义了本应用的数据库表结构.底层可以由不同的数据库封装实现,因为不同的数据库字段类型不一样,因此,跟以往直接用单一数据库(如mysql)建立的应用有很大 ...

  2. Python爬虫开发

    1. 语法入门 Python教程 2. 爬虫学习系列教程 1)宁哥的小站 https://github.com/lining0806/PythonSpiderNotes 2)Python爬虫开发 3) ...

  3. 洛谷P3396 哈希冲突(分块)

    传送门 题解在此,讲的蛮清楚的->这里 我就贴个代码 //minamoto #include<iostream> #include<cstdio> #include< ...

  4. @Transactional之Spring事务深入理解

         Spring支持两种事务方式: 编程式事务:使用的是TransactionTemplate(或者org.springframework.transaction.PlatformTransac ...

  5. 生产阶段Webpack打包【基础打包】

    webpack打包 1.在根目录创建一个 webpack.config.prod.js[它其实就是在开发阶段的基础上增加点东西] 增加了 output 去除了 devServer 2.在package ...

  6. Codeforces Round #365 (Div. 2) B

    Description Little Mishka is a great traveller and she visited many countries. After thinking about ...

  7. 1088 Rational Arithmetic(20 分)

    For two rational numbers, your task is to implement the basic arithmetics, that is, to calculate the ...

  8. 了解Unix进程(3)

    fork() 系统调用可以创建新的进程.然后查看进程ID和父进程ID使用getpid()和getppid()函数. 使用C语言描述: #include <unistd.h> #includ ...

  9. nginx开启HSTS让浏览器强制跳转HTTPS访问

    在上一篇文章中我们已经实现了本地node服务使用https访问了,看上一篇文章 效果可以看如下: 但是如果我们现在使用http来访问的话,访问不了.如下图所示: 因此我现在首先要做的是使用nginx配 ...

  10. PHP面试题基础问题

    1.对于大流量的网站,您采用什么样的方法来解决访问量问题? 首先,确认服务器硬件是否足够支持当前的流量 其次,优化数据库访问. 第三,禁止外部的盗链. 第四,控制大文件的下载. 第五,使用不同主机分流 ...