超级钢琴

【问题描述】

小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。

【输入格式】

第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
N<=500,000,k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

【输出格式】

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

【样例输入】

4 3 2 3
3
2
-6
8

【样例输出】

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。


题解:

设三元组 (l, r, i) 表示以 i 为开始,以某个 j (l<j<r) 为结束组成的和弦能到达的最大美妙度

我们记录前缀和 sum,对于以 i 为开始的前缀, sum[i-1] 是确定的,即只要得到最大的 sum[j] (l<j<r),最大美妙度为 sum[j]-sum[i-1]

即查询 l 到 r 之间的最大的 sum

一开始我们将所有 (i + L - 1, i + R - 1, i) 加入大根堆中,保证和弦长度在 L 到 R 之间

每次取出堆顶的标号,记为s

把这个三元组 (l, r, i) 拆成 (l, s - 1, i) 和 (s + 1, r, i) 两个三元组,再次加入堆中(因为这两个答案也有可能比其他 i 的答案优)

重复这个操作,直到取了k次

 #include<cmath>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 5e5 + ;
int logn;
int n, k;
int lg[maxn], bin[];
int sum[maxn];
inline void Scan(int &x)
{
char c;
bool o = false;
while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
x = c - '';
while(isdigit(c = getchar())) x = x * + c - '';
if(o) x = -x;
}
struct rmq
{
int i, v;
};
rmq maxx[][maxn];
struct interval
{
int l, r, a, b, v;
};
inline bool operator < (interval a, interval b)
{
return a.v < b.v;
}
priority_queue <interval> q;
inline rmq Max(rmq a, rmq b)
{
return (a.v > b.v) ? a : b;
}
inline bool operator < (rmq a, rmq b)
{
return a.v < b.v;
}
inline void Rmq()
{
for(int i = ; i <= logn; ++i)
for(int j = ; j <= n; ++j)
{
if(j + bin[i] - > n) continue;
int k = j + bin[i - ];
maxx[i][j] = max(maxx[i - ][j], maxx[i - ][k]);
}
}
inline int Query(int l, int r)
{
if(l > r) return -;
int len = lg[r - l + ];
return Max(maxx[len][l], maxx[len][r - bin[len] + ]).i;
}
int main()
{
int l, r;
Scan(n), Scan(k), Scan(l), Scan(r);
logn = log2(n);
bin[] = ;
for(int i = ; i <= logn; ++i) bin[i] = bin[i - ] << , lg[bin[i]] = ;
for(int i = ; i <= n; ++i) lg[i] += lg[i - ];
for(int i = ; i <= n; ++i)
{
Scan(sum[i]);
sum[i] += sum[i - ];
maxx[][i] = (rmq) {i, sum[i]};
}
Rmq();
interval s;
int x, u, v, a, b;
for(int i = ; i <= n - l + ; ++i)
{
int a = i + l - , b = min(n, i + r - );
x = Query(a, b);
s = (interval) {a, b, i, x, sum[x] - sum[i - ]};
q.push(s);
}
long long ans = ;
while(k--)
{
s = q.top();
q.pop();
ans += s.v;
u = Query(s.l, s.b - );
v = Query(s.b + , s.r);
if(u > ) q.push((interval) {s.l, s.b - , s.a, u, sum[u] - sum[s.a - ]});
if(v > ) q.push((interval) {s.b + , s.r, s.a, v, sum[v] - sum[s.a - ]});
}
printf("%lld", ans);
}

超级钢琴 BZOJ 2006的更多相关文章

  1. 2006: [NOI2010]超级钢琴 - BZOJ

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

  2. [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)

    [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...

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

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

  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】2006: [NOI2010]超级钢琴(RMQ+优先队列)

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2792  Solved: 1388 Description 小 ...

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

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

  8. bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴

    http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...

  9. 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)

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

随机推荐

  1. 【动态规划】51nod1780 完美序列

    巧妙的转化:f前两维大小开反TLE了一发…… 如果一个序列的相邻两项差的绝对值小于等于1,那么我们说这个序列是完美的. 给出一个有序数列A,求有多少种完美序列排序后和数列A相同. Input 第一行一 ...

  2. pandas归一化操作

    归一化操作有两种 1.max和min的归一化操作 min-max标准化(Min-Max Normalization) 返回结果0~1 公式: 实例: 如: 随机生成假数据如下 df = DataFra ...

  3. centOS下lnamp安装

    首先安装apache,mysql ,最后安装php 1>apache安装 安装:yum install -y httpd 运行:/bin/systemctl start httpd.servic ...

  4. shopnc路由功能分析

    项目核心文件 core/shopld.php if (!@include(BASE_DATA_PATH.'/config/config.ini.php')) exit('config.ini.php ...

  5. 蓝牙stack bluez学习(1)Stack Architecture

    Bluez支持的features Core Specification 4.2 (GAP, L2CAP, RFCOMM, SDP, GATT) Classic Bluetooth (BR/EDR) B ...

  6. LeetCode之Weekly Contest 92

    第一题:转置矩阵 问题: 给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9] ...

  7. Python入门基础--字符编码与文件处理

    字符编码 文本编辑器存取文件的原理 #1.打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放与内存中的,断电后数据丢失 #2.要想永久保存,需要点击保存按钮:编辑器把内 ...

  8. Windows7_64位 NVIDIA 卡 OpenCl环境配置

    序 最近做一个项目需要用到OpenCL,由于之前没有接触过,所以在环境配置第一关就遇到了一些问题,查阅很多资料才配置完成,现在记录如下,希望给一些童鞋一些帮助. 整个步骤也很简单: 了解系统配置,选择 ...

  9. UVA - 1152 4 Values whose Sum is 0问题分解,二分查找

    题目:点击打开题目链接 思路:暴力循环显然会超时,根据紫书提示,采取问题分解的方法,分成A+B与C+D,然后采取二分查找,复杂度降为O(n2logn) AC代码: #include <bits/ ...

  10. Linux数据库忘记密码-修改方法

    一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password "test123"E ...