BZOJ2006:超级钢琴(ST表+堆求前K大区间和)
Description
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。
Input
第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
Output
只有一个整数,表示乐曲美妙度的最大值。
Sample Input
3
2
-6
8
Sample Output
【样例说明】
共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。
HINT
题意:求前K大的连续区间和的和。
思路:之前遇到过,和堆有关,但是当时太弱,没敢做。所以回来参考了一下别人的代码,学习一下发现也没那么难。
(前辈已经写得很清楚了,我就不重复了。如下:
【转】一类经典的问题:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5783868.html
我们发现,固定左端点ii,能够得到长度满足条件的右端点区间
那么我们定义一个五元组(i,L,R,val,pos),其中,ii表示固定下的左端点,L,R表示右端点存在的区间,val表示右端点存在在这个区间的时候最大的价值,pos表示右端点此时的位置
那么我把这个五元组放到堆中,每次取出val最大的,把这个区间裂解,得到的符合条件的两个新的五元组再加入新的区间
具体就是(i,L,R,val,pos)−−>(i,L,pos−1,val′,pos′)+(i,pos+1,R,val′′,pos′′)
至于如何求val和pos,用ST表记录一下前缀和就可以了。
(自己写起来感觉还是蛮简单的。
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
struct in{
int i,L,R,val,pos;
in(){}
in(int ii,int LL,int RR,int vv,int pp):i(ii),L(LL),R(RR),val(vv),pos(pp){}
bool operator<(const in &a) const{ return val<a.val; }
};
priority_queue<in>q;
int dp[maxn][],pos[maxn][];long long ans;
int getmax(int L,int R) //区间最大的位置
{
int t=log2(R-L+);
if(dp[L][t]>dp[R-(<<t)+][t]) return pos[L][t];
return pos[R-(<<t)+][t];
}
int main()
{
int N,K,LL,RR,i,j;
scanf("%d%d%d%d",&N,&K,&LL,&RR);
for(i=;i<=N;i++) scanf("%d",&dp[i][]);
for(i=;i<=N;i++) dp[i][]+=dp[i-][],pos[i][]=i;
for(i=;i<=;i++) //ST表 。
for(j=;j+(<<i)-<=N;j++){
if(dp[j][i-]>dp[j+(<<(i-))][i-]) dp[j][i]=dp[j][i-],pos[j][i]=pos[j][i-];
else dp[j][i]=dp[j+(<<(i-))][i-],pos[j][i]=pos[j+(<<(i-))][i-];
}
for(i=;i+LL-<=N;i++){ //最开始最大个N个数。
int p=getmax(i+LL-,min(N,i+RR-));
q.push(in(i,i+LL-,min(N,i+RR-),dp[p][]-dp[i-][],p));
}
while(K&&!q.empty()){
in now=q.top(); q.pop();
ans+=now.val;
if(now.L<now.pos) {
int p=getmax(now.L,now.pos-);
q.push(in(now.i,now.L,now.pos-,dp[p][]-dp[now.i-][],p));
}
if(now.R>now.pos){
int p=getmax(now.pos+,now.R);
q.push(in(now.i,now.pos+,now.R,dp[p][]-dp[now.i-][],p));
}
K--;
}
printf("%lld\n",ans);
return ;
}
BZOJ2006:超级钢琴(ST表+堆求前K大区间和)的更多相关文章
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
- 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
[BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...
- bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006 每个右端点的左端点在一个区间内:用堆记录端点位置.可选区间,按价值排序:拿出一个后也许 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- 算法导论学习之线性时间求第k小元素+堆思想求前k大元素
对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思 ...
- 牛客第六场 J.Heritage of skywalkert(On求前k大)
题目传送门:https://www.nowcoder.com/acm/contest/144/J 题意:给一个function,构造n个数,求出其中任意两个的lcm的最大值. 分析:要求最大的lcm, ...
- HDU 6041 I Curse Myself(点双联通加集合合并求前K大) 2017多校第一场
题意: 给出一个仙人掌图,然后求他的前K小生成树. 思路: 先给出官方题解 由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉.所以问题就变为有 M 个集合,每个集合里面都有一堆 ...
随机推荐
- HBase 基本操作
如何添加列族 很简单,跟rdbms一样 直接用alter,但是alter之前必须先disable这个表 ---->disable 'test' ...
- UVA - 10603 Fill(隐式图搜索)
题目大意:经典的倒水问题. 给你三个瓶子,体积为a,b,c. 刚開始a.b是空的,c是满的,如今要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多 ...
- 千呼万唤始出来:ArchLinux for Espressobin
前言 原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的链接.图片显示,请访问我的博客原文: http://www.cnblog ...
- nightwatch testing 注意事项
coding style 好的測試項目應該盡量不要使用pause 並且要有驗證的機制 .click('input.btn') //.pause(3000) .waitForElementVisible ...
- final 和static
一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引 ...
- bootstrap之鼠标操作
TouchLongClick package io.appium.android.bootstrap.handler; import android.os.SystemClock; import co ...
- ubuntu 12.04改变源(转载)
来源:http://blog.ubuntusoft.com/ubuntu-update-source.html#.Uq_PP9KBmxh 其它版本的修改方式相识.尽量使用原生工具来修改(见下方). 手 ...
- Struts2实例详解(转载)
Struts2(上) 一. 经典的MVC模式 二. Struts1.x对MVC的实现 三. Struts1.x的主要组件和作用 组件 作用 ActionSer ...
- multiTarget within one project pods manage
step1:file->new->target create 1 targetstep2:change Podfile and update podstep3:check new targ ...
- php 面向对象的三大要素(封装、继承、多态)以及重写(override)和重载(overload)的举例说明
PHP是一种HTML内嵌式的,用来制作动态网页的服务器端的脚本语言.其特点是:开发周期短,稳定安全,简单易学,免费开源,良好的跨平台特性.PHP是一种面向对象的程序设计语言,目前已成为全球最受欢迎的五 ...