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 个集合,每个集合里面都有一堆 ...
随机推荐
- ubuntu怎样打开命令行终端(5种方法)
内容中包含 base64string 图片造成字符过多,拒绝显示
- iOS UI08_TableView界面传值
实现两个界面之间内容的传递 // // MainViewController.m // UI08_TableView界面传值 // // Created by dllo on 15/8/7. // C ...
- 转帖:HttpStatusCode状态说明C#版
Continue 等效于 HTTP 状态 100.Continue 指示客户端可能继续其请求. SwitchingProtocols 等效于 HTTP 状态 101.SwitchingProtocol ...
- sql的一些知识_高级
1.视图 http://www.cnblogs.com/wang666/p/7885934.html 2.存储过程 http://www.cnblogs.com/wang666/p/7920748.h ...
- C - The C Answer (2nd Edition) - Exercise 1-16
/* Revise the main routine of the longest-line program so it will correctly print the length of arbi ...
- 修改 百度地图 infowindow 默认样式
1.百度 api 没有 提供可以修改 infowindow 默认样式的 方法. 如需修改,需要 自定义 替换 默认样式. demo.html <!DOCTYPE html> <htm ...
- 怎样把多个Android Project打包成一个APK
怎样把多个Android Project打包成一个APK(你的项目怎样引用其它项目). 怎样把多个android project 打包成一个apk呢,事实上原理是这种.一个主project引用其它的p ...
- Android 大众点评的接入
这里介绍的是大众点评的团购中的一个接口.就是全部团购信息,其它的接口的实现是大同小异的. 首先,登录大众点评的开发平台->大众点评 . 然后获取到自己的应用的appkey和secret.这个是 ...
- QC3.0快充技术详解
QC3.0 智能手机的电池容量愈来愈大,除了省电能力外,充电速度更成为用户愈来愈重视的特点.高通(Qualcomm)的 Quick Charge 快充技术已成为业界的典范之一,继 Quick Char ...
- __del__删除方法
class dog: def __del__(self): print("删除机制被调用了...") dog1 = dog() del dog1 #在这里是先删除掉了,所以就去上面 ...