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. C/S结构与B/S结构

    按照是否需要访问网络,程序可分为网络程序与非网络程序.其中网络程序又可分为B/S结构与C/S结构. C/S结构是指客户端(Client)/服务器(Server)模式,这种模式的客户端中 需要安装一个R ...

  2. Eclipse web项目更改项目名称

    1. 右键工程:Refactor->Rename,更改项目名称: 2. 修改项目目录下:.project文件 <?xml version="1.0" encoding= ...

  3. vue 组件-父组件传值给子组件

    父组件通过属性,传值给子组件,子组件通过,props数组里的名称来接受父组件传过来的值. HTML部分: <div id="app"> <tmp1 :parent ...

  4. 笨办法学Python - 习题5: More Variables and Printing

    1.习题 5: 更多的变量和打印 学习目标:了解用户输入方法,明白pthon2和Python3之间的用户输入的区别.了解格式化字符串(format string)的概念,学会如何创建包含变量内容的字符 ...

  5. Scrum Meeting 11.11

    成员 今日任务 明日计划 用时 徐越 学习UI设计并重构上传下载界面     赵庶宏       薄霖 UI代码更新     卞忠昊 Xfermode与PorterDuff     武鑫 界面设计:独 ...

  6. c#窗体移动与窗体阴影效果

    //步骤//1.导入代码//2.事件中添加form_1mousedown函数//3.在load函数中定义AnimateWindow语句,注意有两个引用.//4.DllImport若有错误,按shift ...

  7. 读书笔记 之 java编程思想3

    现在已经读到第二章  ,这个发现好多已经能都知道了  但是还是有自己比较生疏的比如说就是 储存到什么地方:书中介绍五种储存的地方 分别为1储存器,2堆栈,3堆4常量储存 5非RAM储存,java的出来 ...

  8. 为什么要读这本书《java编程思想》

    在学校学习编程语言只是浅显的了解,不理解的的东西有很多 ,想通过这本书对java语言有更深的理解,对于以后的学习和工作会有很大的好处.与其了了草草的看你一些书,知其然而不知其所以然,这不是我想要的学习 ...

  9. 第二次作业利用java语言编写计算器进行四则运算

    随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ...

  10. 凡事预则立|项目Beta冲刺准备

    1.讨论组长是否重选的议题和结论. 组员一致认为组长不需要重选,我们都很认可组长的表现,组长的付出我们都看在眼里,我们找不出更适合担任组长的人选. 2.下一阶段需要改进完善的功能. 财富值的布局优化以 ...