2006: [NOI2010]超级钢琴

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 3446  Solved: 1692
[Submit][Status][Discuss]

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,表示按编号从小到大每个音符的美妙度。
N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

Output

只有一个整数,表示乐曲美妙度的最大值。

Sample Input

4 3 2 3
3
2
-6
8

Sample Output

11

【样例说明】
共有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【但是要注意数组不要越界】

查询

我们要查询的区间长度是2的n次方很好办,就是mx[i][n]
但是如果不是呢?
我们可以把原区间分成两个相交的2^n的区间,求二者的最大值即可
具体区间为[l,r],我们令t = log2(r - l + 1),则ans = max(mx[l][t],mx[r - 2^t + 1][t]);
最后我们就可以A啦
【STL似乎不会T】
#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;
}

转载于:https://www.cnblogs.com/Mychael/p/8282785.html

BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】相关推荐

  1. P2048 [NOI2010] 超级钢琴(RMQ 贪心)

    文章目录 题目描述 解析 代码 传送门 题目描述 解析 首先,如果只有一个和弦,那么问题显然简单了 用前缀和结合ST表随便做做即可 然而 这次要求前k大的 怎么办呢? 参照之前有一道序列合并的做法 我 ...

  2. bzoj 2006 [NOI2010]超级钢琴 rmq+堆

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 3708  Solved: 1846 [Submit][Sta ...

  3. NOI2010超级钢琴

    **NOI2010 超级钢琴** **Description** 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出 ...

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

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

  5. P2048 [NOI2010] 超级钢琴(ST表 + 优先队列优化)

    P2048 [NOI2010] 超级钢琴 题目 小 Z 是一个小有名气的钢琴家,最近 C 博士送给了小 Z 一架超级钢琴,小 Z 希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出 ...

  6. 贪心(数据结构):COGS 468. [NOI2010]超级钢琴

    ★★★☆   输入文件:piano.in   输出文件:piano.out   简单对比 时间限制:2 s   内存限制:512 MB 超级钢琴 [问题描述] 小Z是一个小有名气的钢琴家,最近C博士送 ...

  7. P2048-[NOI2010]超级钢琴【RMQ,堆】

    正题 题目链接:https://www.luogu.org/problemnew/show/P2048 题目大意 一个长度为nnn序列aaa.寻找kkk个子序列要求长度在L∼RL\sim RL∼R之间 ...

  8. 洛谷 P2048 [NOI2010]超级钢琴(优先队列,RMQ)

    传送门 我们定义$(p,l,r)=max\{sum[t]-sum[p-1],p+l-1\leq t\leq p+r-1 \}$ 那么因为对每一个$p$来说$sum[p-1]$是一个定值,所以我们只要在 ...

  9. [NOI2010] 超级钢琴

    题目类型:RMQ+堆 传送门:>Here< 题意:给出一个长度为\(N\)的序列\(a\),对于每一个\(i\)作为和弦的起点,长度可以是\(L \rightarrow R\).问所有和弦 ...

最新文章

  1. 你的微服务网关还只在用负载均衡吗?
  2. 一步一步SharePoint 2007之二十三:编写一个最简单的WebPart(1)——创建工程
  3. 使用post向webservice发送请求,并且返回值
  4. 99% 的人都能看懂的「补偿」以及最佳实践
  5. 单词拆分—leetcode139
  6. vue 传递 对象 路由_vue 04 -vue路由对象($route)参数简介以及和router的区别
  7. 计数排序Counting sort
  8. 近5年133个Java面试题 你会几个?
  9. Linux显卡驱动|CUDA卸载和安装|pytorch安装
  10. 如何确认虚拟机被哪台主机锁定以及如何解锁
  11. Windows代替touch命令
  12. 那些年用过的机械键盘
  13. python 自动下载脚本_Python实现115网盘自动下载的方法
  14. 设计师该如何把简历写好?
  15. Python一路走来 DAY15 Javascript
  16. java开发平时看什么东西
  17. 电机控制中标幺的目的
  18. 开启电脑自带的远程控制
  19. DVD-ROM区域码巧破解[转]
  20. H5智能内核-基于MVC架构的全新Zoomla!逐浪CMS2 x3.8发布

热门文章

  1. ARM的交叉编译工具
  2. 【OS】经典调度算法
  3. 计算机组成原理--主存储器
  4. 分享一批国内常用的tracker地址
  5. 动态规划经典算法--最长公共子序列 LCS
  6. 使用AutoMake轻松生成Makefile
  7. 深度学习与计算机视觉(二)线性SVM与Softmax分类器
  8. 在神经网络中使用辍学:不是一个神奇的子弹
  9. linux内核与用户空间的九种通信机制
  10. 李嘉诚那么有钱,为什么还要把国内很多资产卖掉?