超级钢琴

【问题描述】

小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. java基础——随机数问题

    /** * 要求:随机打印50个随机(4-10长度)的字符串,要求字符串包含的范围是所有的英文字母包含大小写和数字, * 按照编码顺序排序,每行打印4个,要求首字符对齐 * @author fanyu ...

  2. Codeforces 517 #B

    http://codeforces.com/contest/1072/problem/B 开始想的只有搜索,时间复杂度$O(4^n)$,明显有问题. 想了半个小时没有思路,然后想到了正难则反,就开始步 ...

  3. matplotlib绘图股票走势图实践

    导入模块 import pandas as pdimport numpy as npfrom pandas import Series,DataFrameimport matplotlib.pyplo ...

  4. 腾讯云Ubuntu服务器修改root密码

    1.修改root密码 执行以下命令,按照提示修改密码 sudo passwd root 2.修改ssh配置 执行以下命令 sudo vi /etc/ssh/sshd_config 找到 PermitR ...

  5. laravel中redis各方法的使用

    在laravel中使用redis自带方法的时候会发现许多原生的方法都不存在了,laravel对其进行了重新的封装但是在文档中并没有找到相关的资料最后在 \vendor\predis\predis\sr ...

  6. 2019 study list

    分析工具: (1)SQL   select from   where   group by having   order by   limit   运算符(算数运算符+-*/.比较运算符>< ...

  7. <原创>在PE最后一节中插入补丁程序(附代码)

    完整文件  http://files.cnblogs.com/Files/Gotogoo/在PE最后一节中插入补丁程序.zip 在PE文件最后一节中插入补丁程序,是最简单也是最有效的一种,因为PE最后 ...

  8. HDU 5396 区间DP 数学 Expression

    题意:有n个数字,n-1个运算符,每个运算符的顺序可以任意,因此一共有 (n - 1)! 种运算顺序,得到 (n - 1)! 个运算结果,然后求这些运算结果之和 MOD 1e9+7. 分析: 类比最优 ...

  9. ModelViewSet的继承关系

  10. Selenium WebDriver- 操作JavaScript的confirm弹窗

    #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...