P2048 [NOI2010]超级钢琴

题目描述

小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,表示按编号从小到大每个音符的美妙度。

输出格式:

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

说明

所有数据满足:-1000 ≤ Ai ≤ 1000,1 ≤ L ≤ R ≤ n且保证一定存在满足要求的乐曲。


题意:求前\(k\)大长度在\(L\)~\(R\)之间的子序列之和

用堆维护\(ST\)表的做法没想到。。

想了个暴力\(nlog^2n\)的做法

枚举子序列左端点\(l\),则可能的右端点为一个长为\(R+1-L\)的序列,我们发现对于可能的右端点\(r\),产生的答案为\(f[r]-f[l-1]\),则每一个左端点固定后减去的值是一定的,只是产生的右端点划过去了。当然每个左端点可能产生多个子序列,我们不能只知道它的最大值。这时候,我们就可以想到拿主席树维护前缀和数组的静态区间第\(k\)值了,然后用一个堆维护每一个左端点所对应的区间取到第几大了。

然而我主席树一直写的不熟调了好久。。


Code:

#include <cstdio>
#include <queue>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
const ll N=2000010;
ll n,k,l0,r0;
ll d[N],score[N],root[N],dat[N<<4],L[N<<4],R[N<<4],num[N],cnt;
pair <ll ,ll > f[N];
ll build(ll l,ll r)
{
ll now=++cnt;
if(l==r) return now;
ll mid=l+r>>1;
L[now]=build(l,mid);
R[now]=build(mid+1,r);
return now;
}
ll rebuild(ll last,ll l,ll r,ll pos)
{
ll now=++cnt;
if(l==r)
{
dat[now]=1;
return now;
}
ll mid=l+r>>1;
if(pos<=mid)
{
L[now]=rebuild(L[last],l,mid,pos);
R[now]=R[last];
}
else
{
L[now]=L[last];
R[now]=rebuild(R[last],mid+1,r,pos);
}
dat[now]=dat[L[now]]+dat[R[now]];
return now;
}
ll query(ll last,ll now,ll l,ll r,ll num)
{
if(l==r) return l;
ll mid=l+r>>1;
if(dat[L[now]]-dat[L[last]]>=num)
return query(L[last],L[now],l,mid,num);
else
return query(R[last],R[now],mid+1,r,num-(dat[L[now]]-dat[L[last]]));
}
void init()
{
scanf("%lld%lld%lld%lld",&n,&k,&l0,&r0);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&score[i]);
score[i]+=score[i-1];
f[i].second=i;
f[i].first=score[i];
}
sort(f+1,f+1+n);
for(ll i=1;i<=n;i++)
{
num[f[i].second]=n-i+1;
d[n-i+1]=f[i].first;
}
root[0]=build(1,n);
for(ll i=1;i<=n;i++)
root[i]=rebuild(root[i-1],1,n,num[i]);
}
priority_queue <pair <ll,ll > > q;
pair <ll,ll > p;
ll top[N];
void work()
{
for(ll i=l0;i<=n;i++)
{
ll r=min(i+r0-l0,n);
p.first=d[query(root[i-1],root[r],1,n,++top[i])]-score[i-l0];
p.second=i;
q.push(p);
}
ll ans=0;
while(k--)
{
ll now=q.top().second;
ans+=q.top().first;
q.pop();
if(top[now]>=min(r0-l0,n-now)+1) continue;
p.first=d[query(root[now-1],root[min(now+r0-l0,n)],1,n,++top[now])]-score[now-l0];
p.second=now;
q.push(p);
}
printf("%lld\n",ans);
}
int main()
{
init();
work();
return 0;
}

2018.7.5

洛谷 P2048 [NOI2010]超级钢琴 解题报告的更多相关文章

  1. [洛谷P2048] [NOI2010] 超级钢琴

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

  2. 洛谷P2048 [NOI2010]超级钢琴 题解

    2019/11/14 更新日志: 近期发现这篇题解有点烂,更新一下,删繁就简,详细重点.代码多加了注释.就酱紫啦! 正解步骤 我们需要先算美妙度的前缀和,并初始化RMQ. 循环 \(i\) 从 \(1 ...

  3. 洛谷 P2048 [NOI2010]超级钢琴 || Fantasy

    https://www.luogu.org/problemnew/show/P2048 http://www.lydsy.com/JudgeOnline/problem.php?id=2006 首先计 ...

  4. 洛谷 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]$是一个定值,所以我们只要在 ...

  5. 洛谷P0248 [NOI2010] 超级钢琴 [RMQ,贪心]

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

  6. 洛谷 P3990 [SHOI2013]超级跳马 解题报告

    P3990 [SHOI2013]超级跳马 题目描述 现有一个\(n\) 行 \(m\) 列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘. ...

  7. P2048 [NOI2010]超级钢琴(RMQ+堆+贪心)

    P2048 [NOI2010]超级钢琴 区间和--->前缀和做差 多次查询区间和最大--->前缀和RMQ 每次取出最大的区间和--->堆 于是我们设个3元组$(o,l,r)$,表示左 ...

  8. 【题解】P2048 [NOI2010]超级钢琴

    [题解][P2048 NOI2010]超级钢琴 一道非常套路的题目.是堆的套路题. 考虑前缀和,我们要是确定了左端点,就只需要在右端区间查询最大的那个加进来就好了.\(sum_j-sum_{i-1}​ ...

  9. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

随机推荐

  1. [Unity3D]MonoDeveloper快捷键(补全代码补全引用中文乱码tab转空格)

    Hello亲爱的观众朋友们大家好,我是09. vs支持各种插件,一般推荐用vs.不过总有人(例如我)由于各种原因用MonoDeveloper.苦于每次上网找各种设置,此处集中写下我用MonoDevel ...

  2. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第2节: FastThreadLocal的set方法

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第二节: FastThreadLocal的set方法 上一小节我们学习了FastThreadLocal的创建和 ...

  3. crosstool-ng搭建交叉编译环境注意事项

    一,crosstool-ng的下载及编译方法 可以参考如下网站: http://www.crosstool-ng.org/ 二,编译过程注意事项 1)如果遇到有些代码包不能下载,请依据指定版本,在这里 ...

  4. unzip/tar命令详解

    博客目录总纲首页 原文链接:https://www.cnblogs.com/zdz8207/p/3765604.html Linux下的压缩解压缩命令详解及实例 实例:压缩服务器上当前目录的内容为xx ...

  5. string类型和int类型之间的转换

    一.string转int 1. 使用string流 /* 字符串转整型 */ /* * istringstream:从 string 读取数据 * ostringstream:向 string 写入数 ...

  6. “Hello World!“”团队第七周召开的第三次会议

    今天是我们团队“Hello World!”团队第七周召开的第三次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.代码 一 ...

  7. 使用sql查询mysql/oracle/sql server/gp数据库中指定表的字段信息(字段名/字段类型/字段长度/是否是主键/是否为空)

    1,根据数据库类型拼接不同URL /** * 根据类型不同拼接连接的URL * @param dbType 1:mysql.2:oracle.3:sql server.4:gp * @param ip ...

  8. MathExam6378

    我的第一个程序 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 15 10 • Estima ...

  9. 20135234mqy 实验二 Java面向对象程序设计

      北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1352  姓名:mqy  学号:20135234 成绩:             指导教师: ...

  10. eclipse异常关闭,而Tomcat然在运行解决方法

    1.eclipse异常关闭,而Tomcat然在运行,再启动tomcat会出现端口冲突 解决方法:打开任务管理器,找到javaw.exe,点击关闭,就可以了