BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】
2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MB
Submit: 3446 Solved: 1692
[Submit][Status][Discuss]
Description
Input
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。
我们利用前缀和可以很快得到最大的答案
对于每个点i,我们只要求出sum[i + L - 1] 到 sum[i + R - 1]中最大的值就可以得到以i为左端点的最大值
我们设这样一个值为三元组(i,l,r)的值,表示以i开头右端点在[l,r]内的区间最大和
利用这个,我们求出最大值后,求第二大的值可能以其它i开头,也可能仍然以当前i开头,我们就把当前(i,l,r)分裂成
(i,l,t - 1)和(i,t + 1,r)就可以了
重复K次,即得结果
但是如何做到快速求区间最大值呢?
这就用到了RMQ算法【ST表】
ST表是用以解决区间最大值无修改的算法,预处理O(nlogn),查询O(1)
可以说在没有修改的情况下比线段树优很多
具体实现:
预处理
我们设mx[i][j]表示以[i,i + 2^j - 1],也就是以i开头长度为2^j的区间的最大值
利用倍增的方法,mx[i][j] = max(mx[i][j - 1],mx[i + 2^(j - 1)][j - 1]);
我们可以处理出所有的mx【但是要注意数组不要越界】
查询
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define mp(a,b,c,d) (node){a,b,c,d}
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N,K,L,R,sum[maxn],mx[maxn][30],Log[maxn];
LL ans = 0;
struct node{int i,l,r,t;};
inline bool operator <(const node& a,const node& b){return sum[a.t] - sum[a.i - 1] < sum[b.t] - sum[b.i - 1];}
priority_queue<node,vector<node> > q;
void RMQ(){
Log[0] = -1;
for (int i = 1; i <= N; i++) Log[i] = Log[i >> 1] + 1;
int t = Log[N];
REP(i,N) mx[i][0] = i;
for (int i = N; i; i--){
for (int j = 1; j <= t; j++){
if (i + (1 << j) - 1 > N) break;
int t1 = mx[i][j - 1],t2 = mx[i + (1 << j - 1)][j - 1];
mx[i][j] = sum[t1] > sum[t2] ? t1 : t2;
}
}
}
inline int Query(int l,int r){
if (l == r) return l;
int t = Log[r - l + 1],t1 = mx[l][t],t2 = mx[r - (1 << t) + 1][t];
return sum[t1] > sum[t2] ? t1 : t2;
}
void solve(){
node u;
REP(i,N){
if (i + L - 1 > N) break;
int r = min(i + R - 1,N);
q.push(mp(i,i + L - 1,r,Query(i + L - 1,r)));
}
for (int i = 1; i <= K; i++){
u = q.top(); q.pop();
ans += sum[u.t] - sum[u.i - 1];
if (u.t - 1 >= u.l) q.push(mp(u.i,u.l,u.t - 1,Query(u.l,u.t - 1)));
if (u.t + 1 <= u.r) q.push(mp(u.i,u.t + 1,u.r,Query(u.t + 1,u.r)));
}
}
int main(){
N = RD(); K = RD(); L = RD(); R = RD();
REP(i,N) sum[i] = sum[i - 1] + RD();
RMQ();
solve();
cout<<ans<<endl;
return 0;
}
BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】的更多相关文章
- BZOJ2006[NOI2010]超级钢琴——堆+主席树
题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...
- bzoj2006 [NOI2010]超级钢琴 (及其拓展)
bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...
- P2048 [NOI2010]超级钢琴(RMQ+堆+贪心)
P2048 [NOI2010]超级钢琴 区间和--->前缀和做差 多次查询区间和最大--->前缀和RMQ 每次取出最大的区间和--->堆 于是我们设个3元组$(o,l,r)$,表示左 ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴
http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...
- 【BZOJ 2006】2006: [NOI2010]超级钢琴(RMQ+优先队列)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2792 Solved: 1388 Description 小 ...
- Bzoj 2006: [NOI2010]超级钢琴 堆,ST表
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2222 Solved: 1082[Submit][Statu ...
- [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 3591 Solved: 1780[Submit][Statu ...
- [NOI2010]超级钢琴(RMQ+堆)
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负 ...
随机推荐
- UpdateLog
2014-10-20 增加数据适配器,使支持多数据库类型2015-01-08 增加没有主键ID的抽象类,使能自义主键字段实现MODEL 增加虚拟字段转换,将指定函数或语法转换为对象属性,灵活性更大了 ...
- Qt-QML-安卓编译问题
Qt的强大在于跨平台,但是在某些地方做的还是不好,想我这种白痴,在编译安卓的时候就遇到新的问题,我在PC上面编译没有问题的,跑到安卓上面就会出现问题,我猜测应该是Qt的下面的编译的时候,用的还是旧的安 ...
- python——一些常用的方法类
测试的时候经常需要使用一些方法都整理放在一起,方便调用 首先一些基本的配置引入 localReadConfig = readConfig.ReadConfig() proDir = readConfi ...
- katalon系列四:使用Katalon Studio录制WEB自动化脚本
一.点击图1工具栏中的+号,选Test Case,新建一个用例. 图1 二.接着点图1录制按钮(地球上有个红点图标),打开的Web Recorder中URL输入百度的地址,浏览器选择Chrome,点击 ...
- 阿里云ECS下Ubuntu 16.04系统安装python3.6.5 环境并设置为默认
一.添加python3.6安装包并安装: 二.修改系统默认python版本为3.6: 三.安装并升级pip版本: 一.添加python3.6安装包并安装: sudo apt-get install s ...
- mysql新手入门随笔4
40.子查询:出现在其他SQL语句里的SELECT语句 例如:SELECT sname,mark FROM student WHERE mark = (SELECT max(mark) FROM st ...
- Unity编辑器 - 使用GL绘制控件
Unity编辑器 - 使用GL绘制控件 控件较为复杂时,可能造成界面卡顿,在EditorGUI中也可以灵活使用GL绘制来提升性能. 以绘制线段为例: using UnityEngine; using ...
- List和String数组相互转化
在工作中经常会遇到需要String[] 参数的地方,我们可以先定义一个list,再转成String[] 来使用,使用list的好处自然是可以随时方便的添加删除元素,下面是方法: List list = ...
- [HNOI2018]转盘
[HNOI2018]转盘 给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 ...
- 剑指offer-栈的压入弹出序列21
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...