题目大意:给定一个序列。找到k个长度在[l,r]之间的序列。使得和最大

暴力O(n^2logn),肯定过不去

看到这题的第一眼我OTZ了一下午。。。

后来研究了非常久别人的题解才弄明确怎么回事。。。蒟蒻果然不能理解大神的思路啊0.0

首先维护前缀和,那么以第i个元素结尾的和最大的序列自然就是sum[i]-min{sum[j]}(i-r<=j<=i-l)

然后我们维护一个大根堆,每取走一个以i为结尾的元素,增加sum[i]-2thmin{sum[j]}。再取走这个元素就增加sum[i]-3thmin{sum[j]},以此类推

维护区间第k小,划分树。不说啥了吧 尼玛本大爷的划分树竟然还写挂了0.0

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #define M 500500
  6. using namespace std;
  7. typedef pair<int,int> abcd;
  8. typedef long long ll;
  9. int n,k,l,r;ll ans;
  10. int sum[M],a[M],b[M],c[M],s[22][M],now[M];
  11. abcd heap[M];int top;
  12. void insert(abcd x)
  13. {
  14. heap[++top]=x;
  15. int t=top;
  16. while(t>1&&heap[t]>heap[t>>1])
  17. swap(heap[t],heap[t>>1]),t>>=1;
  18. }
  19. void pop()
  20. {
  21. heap[1]=heap[top--];
  22. int t=2;
  23. while(t<=top)
  24. {
  25. if(t<top&&heap[t+1]>heap[t])
  26. t++;
  27. if(heap[t]>heap[t>>1])
  28. swap(heap[t],heap[t>>1]),t<<=1;
  29. else
  30. break;
  31. }
  32. }
  33. void Build_Tree(int l,int r,int dpt)
  34. {
  35. int i,mid=l+r>>1;
  36. int l1=l,l2=mid+1;
  37. int left=mid-l+1;
  38. if(l==r)
  39. return ;
  40. for(i=l;i<=r;i++)
  41. left-=a[i]<c[mid];
  42. for(i=l;i<=r;i++)
  43. {
  44. if(a[i]<c[mid]||a[i]==c[mid]&&left)
  45. b[l1++]=a[i],s[dpt][i]=i==l?1:s[dpt][i-1]+1,left-=a[i]==c[mid];
  46. else
  47. b[l2++]=a[i],s[dpt][i]=i==l?
  48.  
  49. 0:s[dpt][i-1];
  50. }
  51. memcpy(a+l,b+l,r-l+1<<2);
  52. Build_Tree(l,mid,dpt+1);
  53. Build_Tree(mid+1,r,dpt+1);
  54. }
  55. int Get_Ans(int l,int r,int dpt,int x,int y,int k)
  56. {
  57. int mid=l+r>>1;
  58. int l1=x==l?
  59.  
  60. 0:s[dpt][x-1],l2=s[dpt][y];
  61. if(l==r)
  62. return c[mid];
  63. if(k<=l2-l1)
  64. return Get_Ans(l,mid,dpt+1,l+l1,l+l2-1,k);
  65. else
  66. return Get_Ans(mid+1,r,dpt+1,(mid+1)+(x-l-l1),(mid+1)+(y-l+1-l2)-1,k-l2+l1);
  67. }
  68. int main()
  69. {
  70.  
  71. //freopen("piano.in","r",stdin);
  72. //freopen("piano.out","w",stdout);
  73.  
  74. int i;
  75. cin>>n>>k>>l>>r;
  76. for(i=1;i<=n;i++)
  77. scanf("%d",&sum[i]),sum[i]+=sum[i-1];
  78. memcpy(a,sum,n+1<<2);
  79. memcpy(c,sum,n+1<<2);
  80. sort(c,c+n+1);
  81. Build_Tree(0,n,0);
  82. for(i=l;i<=n;i++)
  83. {
  84. now[i]=1;
  85. int temp=Get_Ans(0,n,0,max(i-r,0),i-l,1);
  86. insert( make_pair(sum[i]-temp,i) );
  87. }
  88. for(i=1;i<=k;i++)
  89. {
  90. abcd temp=heap[1];pop();
  91. if( now[temp.second]!=(temp.second-l)-( max(temp.second-r,0) )+1 )
  92. insert( make_pair(sum[temp.second]-Get_Ans(0,n,0,max(temp.second-r,0),temp.second-l,++now[temp.second]),temp.second) );
  93. ans+=temp.first;
  94. }
  95. cout<<ans<<endl;
  96. }

BZOJ 2006 NOI2010 超级钢琴 划分树+堆的更多相关文章

  1. BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]

    题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...

  2. bzoj 2006 [NOI2010]超级钢琴——ST表+堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...

  3. BZOJ 2006: [NOI2010]超级钢琴 ST表+堆

    开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...

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

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

  5. BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )

    取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<c ...

  6. BZOJ 2006: [NOI2010]超级钢琴

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

  7. 洛谷 P2048 BZOJ 2006 [NOI2010]超级钢琴

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

  8. BZOJ 2006 [NOI2010]超级钢琴 (堆+主席树)

    题面:BZOJ传送门 洛谷传送门 让你求前$K$大的子序列和,$n\leq 5*10^{5}$ 只想到了个$nlog^{2}n$的做法,似乎要被卡常就看题解了.. 好神奇的操作啊,我傻了 我们把序列和 ...

  9. BZOJ.2006.[NOI2010]超级钢琴(贪心 堆)

    BZOJ 洛谷 思路和BZOJ3784一样,用前缀和+堆维护.做那题吧,不赘述啦. (没错我就是水一个AC) //54620kb 1060ms #include <queue> #incl ...

随机推荐

  1. android在Canvas使用drawBitmap画一幅画

    1.画图的主要方法 //Bitmap:图片对象,left:向左偏移.top: 顶部偏移     drawBitmap(Bitmap bitmap, float left, float top, Pai ...

  2. Qt中提高sqlite的读写速度(使用事务一次性写入100万条数据)

    SQLite数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很好时的过程,会极大地影响数据库存取的速度.例如:向数据库中插入100万条数 ...

  3. poj 动态规划的主题列表和总结

    此文转载别人,希望自己可以做完这些题目. 1.POJ动态规划题目列表 easy:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, ...

  4. 初始化openwrt的rootpassword

    更改openwrt源代码 shadow 文件 package/base-files/files/etc/shadow shadow 文件參考http://blog.csdn.net/u01164188 ...

  5. oschina 编程语言

    编程语言 Java C/C++ Objective-C PHP Perl Python Ruby C# .NET ASP Google Go D语言 Groovy Scala JavaScript T ...

  6. 传京东副总裁蒉莺春或将接管POP业务-搜狐IT

    传京东副总裁蒉莺春或将接管POP业务-搜狐IT 传京东副总裁蒉莺春或将接管POP业务

  7. C#的百度地图开发(一)发起HTTP请求

    原文:C#的百度地图开发(一)发起HTTP请求 百度地图的开发文档中给出了很多的事例,而当用到具体的语言来开发时,又会有些差异.我是使用C#来开发的.在获取相应的数据时,需要通过URL传值,然后获取相 ...

  8. 啊上班我排名可人皮号i家狂喷

    http://pan.baidu.com/share/link?shareid=3011665141&uk=338692646&third=15                http ...

  9. getline与get函数的区别

    get()函数相对getline来说使用方法要灵活的多了. 1.   int get()是指从流中抽取单个字符并返回,这个是没有參数的形式.由于c++不像c语言使用getchar() 2.istrea ...

  10. NYOJ 104 最大子矩阵(二维DP)

    最大和 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描写叙述 给定一个由整数组成二维矩阵(r*c),如今须要找出它的一个子矩阵,使得这个子矩阵内的全部元素之和最大,并把这个 ...