【BZOJ2006】超级钢琴(主席树,优先队列)

题面

BZOJ

题解

既然是一段区间

首先就要变成单点

所以求一个前缀和

这个时候贪心很明显了:

枚举每一个点和可以和它组成一段的可行的点

全部丢进一个堆里面

取出最大的\(K\)个就行了

但是,很显然,我们做不到都取出来

所以,考虑怎么优化这个过程

每次堆里面对于每个点就先维护一个最大贡献

显然的,只有取出了最大贡献,才会取出次大贡献

那么,最大/次大/\(K\)大贡献怎么算?

一个点,能够和他组成和弦的是一个连续的区间

最大的贡献就是它和区间最小值的差

依次类推

就是区间第\(K\)大

所以搞一棵主席树

维护一下区间第\(K\)大就好啦

再用堆每次取出/加入即可

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define MAX 510000
  13. inline int read()
  14. {
  15. int x=0,t=1;char ch=getchar();
  16. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  17. if(ch=='-')t=-1,ch=getchar();
  18. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  19. return x*t;
  20. }
  21. struct Data{int v,id,k;};
  22. bool operator<(Data a,Data b){return a.v<b.v;}
  23. priority_queue<Data> Q;
  24. struct Node
  25. {
  26. int ls,rs;
  27. int sum;
  28. }t[MAX<<6];
  29. int tot,S[MAX],top,rt[MAX],L,R,n,K;
  30. int a[MAX];
  31. void Modify(int &now,int ff,int l,int r,int pos,int w)
  32. {
  33. t[now=++tot]=t[ff];t[now].sum+=w;
  34. if(l==r)return;
  35. int mid=(l+r)>>1;
  36. if(pos<=mid)Modify(t[now].ls,t[ff].ls,l,mid,pos,w);
  37. else Modify(t[now].rs,t[ff].rs,mid+1,r,pos,w);
  38. }
  39. int Query(int A,int B,int l,int r,int K)
  40. {
  41. if(l==r)return l;
  42. int mid=(l+r)>>1;
  43. int sum=t[t[A].ls].sum-t[t[B].ls].sum;
  44. if(sum<K)return Query(t[A].rs,t[B].rs,mid+1,r,K-sum);
  45. else return Query(t[A].ls,t[B].ls,l,mid,K);
  46. }
  47. int main()
  48. {
  49. n=read()+1;K=read();L=read();R=read();
  50. for(int i=2;i<=n;++i)S[++top]=a[i]=a[i-1]+read();S[++top]=0;
  51. sort(&S[1],&S[top+1]);
  52. top=unique(&S[1],&S[top+1])-S-1;
  53. for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[top+1],a[i])-S;
  54. for(int i=1;i<=n;++i)Modify(rt[i],rt[i-1],1,top,a[i],1);
  55. for(int i=L+1;i<=n;++i)
  56. {
  57. Data x;x.id=i;x.k=1;
  58. x.v=S[a[i]]-S[Query(rt[i-L],rt[max(0,i-R-1)],1,top,1)];
  59. Q.push(x);
  60. }
  61. long long ans=0;
  62. while(K--)
  63. {
  64. Data x=Q.top();Q.pop();
  65. ans+=x.v;
  66. if(x.k==min(x.id-L,R-L+1))continue;
  67. x.k++;
  68. x.v=S[a[x.id]]-S[Query(rt[x.id-L],rt[max(0,x.id-R-1)],1,top,x.k)];
  69. Q.push(x);
  70. }
  71. printf("%lld\n",ans);
  72. return 0;
  73. }

【BZOJ2006】超级钢琴(主席树,优先队列)的更多相关文章

  1. bzoj2006 noi2010 超级钢琴 主席树 + 优先队列

    Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2435  Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送 ...

  2. [NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]

    题面: 传送门 思路: 首先容易想到用堆维护的O(n2logn)暴力 那么肯定就是在这个基础上套数据结构了[愉快] 然而我因为过于蒟蒻......只想得到主席树暴力***过去的方法 大概就是把前缀和算 ...

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

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

  4. [NOI2010]超级钢琴 主席树

    [NOI2010]超级钢琴 链接 luogu 思路 和12省联考的异或粽子一样. 堆维护n个左端点,每次取出来再放回去次 代码 #include <bits/stdc++.h> #defi ...

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

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

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

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

  7. BZOJ2006 超级钢琴

    Description ​ 给定一个长度为n的区间,询问前k大的区间和,区间长度\(\in [L, R]\). $ n, k <= 500000$ Solution ​ 首先求前缀和.把一个区间 ...

  8. 【BZOJ2006】【NOI2010】超级钢琴(主席树,优先队列)

    [BZOJ2006]超级钢琴(主席树,优先队列) 题面 BZOJ 题解 既然是一段区间 首先就要变成单点 所以求一个前缀和 这个时候贪心很明显了: 枚举每一个点和可以和它组成一段的可行的点 全部丢进一 ...

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

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

随机推荐

  1. python中的变量,运算符

    范例: name = 'Crossin' myVar = 123 price = 5.99 visible = True “=”的作用是把右边的值赋予给左边的变量. python中有四种较为常见的数据 ...

  2. stderr,stdout,a.txt缓冲区别

    #include<stdlib.h>#include<stdio.h>#include<string.h>#include<error.h>#inclu ...

  3. Mysql大数据备份和增量备份及还原

    目前主流的有两个工具可以实现物理热备:ibbackup和xtrabackup ;ibbackup是需要授权价格昂贵,而xtrabackup功能比ibbackup强大而且是开源的 Xtrabackup提 ...

  4. [Python Study Notes]异常处理

    正则表达式 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 异常处理 断言(Assertions) python标准异常 ...

  5. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  6. Deep Learning for Information Retrieval

    最近关注了一些Deep Learning在Information Retrieval领域的应用,得益于Deep Model在对文本的表达上展现的优势(比如RNN和CNN),我相信在IR的领域引入Dee ...

  7. ERROR namenode.NameNode: Failed to start namenode. java.lang.IllegalArgument

    这个问题一般是配置文件配置没有配置好的原因

  8. C语言_初步了解一下指针

    指针的基本概念 在计算机中,所有的数据都是存放在存储器中的. 一般把存储器中的一个字节称为一个内存单元, 不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等.为了正确地访问这 ...

  9. 2道acm编程题(2014):1.编写一个浏览器输入输出(hdu acm1088);2.encoding(hdu1020)

    //1088(参考博客:http://blog.csdn.net/libin56842/article/details/8950688)//1.编写一个浏览器输入输出(hdu acm1088)://思 ...

  10. Java多线程,判断其他线程是否结束的方法

    方法1:通过Thread类中的isAlive()方法判断线程是否处于活动状态. 线程启动后,只要没有运行完毕,都会返回true. [注]如果只是要等其他线程运行结束之后再继续操作,可以执行t.join ...