【BZOJ2006】[NOI2010] 超级钢琴(堆+RMQ)
大致题意: 要你求出区间和前\(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)的更多相关文章
- BZOJ2006[NOI2010]超级钢琴——堆+主席树
题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...
- bzoj2006 [NOI2010]超级钢琴 (及其拓展)
bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...
- BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MB Submit: 3446 Solved: 1692 [Submit][Sta ...
- P2048 [NOI2010]超级钢琴(RMQ+堆+贪心)
P2048 [NOI2010]超级钢琴 区间和--->前缀和做差 多次查询区间和最大--->前缀和RMQ 每次取出最大的区间和--->堆 于是我们设个3元组$(o,l,r)$,表示左 ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴
http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...
- 【BZOJ 2006】2006: [NOI2010]超级钢琴(RMQ+优先队列)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2792 Solved: 1388 Description 小 ...
- Bzoj 2006: [NOI2010]超级钢琴 堆,ST表
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2222 Solved: 1082[Submit][Statu ...
- [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 3591 Solved: 1780[Submit][Statu ...
- [NOI2010]超级钢琴(RMQ+堆)
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负 ...
随机推荐
- Unity---DOTween插件学习(4)---Andy老师自己写的动态效果工具插件
本文及系列参考于Andy老师的DOTween系列 欢迎大家关注Andy老师 13.动态效果工具插件 这个插件是Andy老师自己利用DOTween写的按钮点击和显示的效果控件,有非常多的种类,还是挺好用 ...
- thinkphp5 join使用注意
A表有id,name,time等字段, B表有id,type,uid,email,address等字段. A表中的id和B表中的uid对应. Db::table(A表)->alias('a') ...
- 树的计数 Prufer序列+Cayley公式
先安利一发.让我秒懂.. 第一次讲这个是在寒假...然而当时秦神太巨了导致我这个蒟蒻自闭+颓废...早就忘了这个东西了... 结果今天老师留的题中有两道这种的:Luogu P4981 P4430 然后 ...
- Codeforces Round #129 (Div. 2) C
Description The Little Elephant very much loves sums on intervals. This time he has a pair of intege ...
- Django的用户认证组件,自定义分页
一.用户认证组件 1.auth模块 from django.conrtrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1)authen ...
- 有效使用Mock编写java单元测试
Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构.然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编 ...
- 练习六:斐波那契数列(fibonacci)
题目:斐波那契数列. 程序分析:斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.……. 在数学上,斐波那契数列 ...
- mycat学习日记:关于联表查询
https://www.cnblogs.com/toulon/p/4832895.html 在使用数据库中间件之前,我就想到分库分表的操作对于联表操作可能会显得非常复杂.因为如果数据是分片存储的,如果 ...
- javaweb项目导入myecplise出错
项目导入出错:移动项目的时候.classpath .project不要删 build path -> use for source floder 把某一文件夹当作源码文件夹 bulid path ...
- linux增加/删除虚拟IP地址
网卡上增加一个IP: ifconfig eth0:1 192.168.0.1 netmask 255.255.255.0 删除网卡的第二个IP地址: ip addr del 192.168.0.1 d ...