点此看题面

大致题意: 要你求出区间和前\(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\)大的右端点,所以,对于一个答案,我们在将其统计之后,需要将它重新拆成两部分再分别扔回堆中,这样就能保证没有遗漏了。

代码

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define N 500000
  4. using namespace std;
  5. int n,m,l,r,a[N+5],Log2[N+5];
  6. LL sum[N+5];
  7. struct RMQ//RMQ区间最值
  8. {
  9. LL Max,Maxer;//Max存储最大的数,Maxer存储最大的数的编号
  10. bool operator < (const RMQ a) const//比较两个RMQ结构体的大小
  11. {
  12. return Max<a.Max;//比较最大的数的大小
  13. }
  14. }R[N+5][25];
  15. struct key
  16. {
  17. LL x,y,s,val,pos;//x,y表示区间能选的范围,pos,s表示选择了的区间的范围,val表示这个选择了的区间的区间和
  18. bool operator < (const key a) const//比较两个key结构体的大小
  19. {
  20. return val<a.val;//比较区间和的大小
  21. }
  22. };
  23. priority_queue<key> h;//一个堆
  24. inline char tc()
  25. {
  26. static char ff[100000],*A=ff,*B=ff;
  27. return A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++;
  28. }
  29. inline void read(int &x)
  30. {
  31. x=0;int f=1;char ch;
  32. while(!isdigit(ch=tc())) if(ch=='-') f=-1;
  33. while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
  34. x*=f;
  35. }
  36. inline void write(LL x)
  37. {
  38. if(x<0) putchar('-'),x=-x;
  39. if(x>9) write(x/10);
  40. putchar(x%10+'0');
  41. }
  42. inline void Start()//预处理
  43. {
  44. for(register int j=1;j<=25;++j)//预处理出RMQ
  45. for(register int i=1;i+(1<<(j-1))<=n;++i)
  46. R[i][j]=max(R[i][j-1],R[i+(1<<(j-1))][j-1]);
  47. for(register int i=2;i<=n;++i) Log2[i]=Log2[i>>1]+1;//预处理出Log2[],减少精度误差
  48. }
  49. inline int Maxer(int l,int r)//返回这段区间内能使区间和最大的位置
  50. {
  51. int k=Log2[r-l+1];//一个RMQ的过程
  52. return max(R[l][k],R[r-(1<<k)+1][k]).Maxer;
  53. }
  54. int main()
  55. {
  56. register int i;
  57. 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];
  58. Start();
  59. 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});//先将每一个区间加入堆
  60. LL ans=0;//ans统计答案
  61. while(m--)
  62. {
  63. key k=h.top();
  64. h.pop(),ans+=k.val;//更新ans
  65. 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});//若左边还有区间,就将左边一部分重新扔入堆中
  66. 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});//若右边还有区间,就将右边一部分重新扔入堆中
  67. }
  68. return write(ans),0;
  69. }

【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. Unity---DOTween插件学习(4)---Andy老师自己写的动态效果工具插件

    本文及系列参考于Andy老师的DOTween系列 欢迎大家关注Andy老师 13.动态效果工具插件 这个插件是Andy老师自己利用DOTween写的按钮点击和显示的效果控件,有非常多的种类,还是挺好用 ...

  2. thinkphp5 join使用注意

    A表有id,name,time等字段, B表有id,type,uid,email,address等字段. A表中的id和B表中的uid对应. Db::table(A表)->alias('a') ...

  3. 树的计数 Prufer序列+Cayley公式

    先安利一发.让我秒懂.. 第一次讲这个是在寒假...然而当时秦神太巨了导致我这个蒟蒻自闭+颓废...早就忘了这个东西了... 结果今天老师留的题中有两道这种的:Luogu P4981 P4430 然后 ...

  4. Codeforces Round #129 (Div. 2) C

    Description The Little Elephant very much loves sums on intervals. This time he has a pair of intege ...

  5. Django的用户认证组件,自定义分页

    一.用户认证组件 1.auth模块 from django.conrtrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1)authen ...

  6. 有效使用Mock编写java单元测试

    Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构.然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编 ...

  7. 练习六:斐波那契数列(fibonacci)

    题目:斐波那契数列. 程序分析:斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.……. 在数学上,斐波那契数列 ...

  8. mycat学习日记:关于联表查询

    https://www.cnblogs.com/toulon/p/4832895.html 在使用数据库中间件之前,我就想到分库分表的操作对于联表操作可能会显得非常复杂.因为如果数据是分片存储的,如果 ...

  9. javaweb项目导入myecplise出错

    项目导入出错:移动项目的时候.classpath .project不要删 build path -> use for source floder 把某一文件夹当作源码文件夹 bulid path ...

  10. linux增加/删除虚拟IP地址

    网卡上增加一个IP: ifconfig eth0:1 192.168.0.1 netmask 255.255.255.0 删除网卡的第二个IP地址: ip addr del 192.168.0.1 d ...