这道题题号很清新啊!第一次开NOI的题,因为最近考到了这道题的升级版。

我们先考虑\(O(n^2)\)大暴力,就是枚举前后端点然后开一个前缀和减一下即可。

然后引入正解,我们设一个三元组\(F(s,l,r)\)表示以\(s\)为左端点,右端点的范围在\([l,r]\)的时候最优的右端点为多少。

左端点确定了,右端点的区间也确定了,那么右端点的位置怎么求?

RMQ直接查询即可。由于要求值最大,因此我们RMQ出前缀和最大值即可

然后我们就可以得到一些三元组,考虑如何计算答案。

我们还是通过取最大值这点性质想到堆。因此我们用大根堆来维护,而要维护的东西应该就是这个区间的值了。

然后前缀和的作用就出来了。我们在比较时让键值为\(sum_t-sum_{s-1}\)即可。

当我们取出一个解时,注意以\(s\)为左端点的区间就不是没有用了,我们可以把它按选择的最优位置分裂成两半然后再扔回堆里为后续的做准备。

具体实现看CODE

#include<cstdio>
#include<cctype>
#include<queue>
using namespace std;
const int N=500005,P=25;
int n,k,l,r,sum[N],log[N];
long long ans;
struct data
{
int s,l,r,t;
bool operator <(const data x) const { return sum[x.t]-sum[x.s-1]>sum[t]-sum[s-1]; }
};
struct RMQ
{
int x,num;
}f[N][P];
priority_queue<data> big;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;
while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); x*=flag;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
inline void log_init(void)
{
for (register int i=2;i<=n;++i)
log[i]=log[i>>1]+1;
}
inline void RMQ_init(void)
{
for (register int j=1;j<P;++j)
for (register int i=1;i+(1<<j)-1<=n;++i)
f[i][j]=f[i][j-1].x>f[i+(1<<j-1)][j-1].x?f[i][j-1]:f[i+(1<<j-1)][j-1];
}
inline int query(int l,int r)
{
int k=log[r-l+1];
return f[l][k].x>f[r-(1<<k)+1][k].x?f[l][k].num:f[r-(1<<k)+1][k].num;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(n); read(k); read(l); read(r);
for (i=1;i<=n;++i)
read(sum[i]),sum[i]+=sum[i-1],f[i][0]=((RMQ){sum[i],i});
log_init(); RMQ_init();
for (i=1;i<=n;++i)
if (i+l-1<=n) big.push((data){i,i+l-1,min(n,i+r-1),query(i+l-1,min(n,i+r-1))});
while (k--)
{
data now=big.top(); big.pop(); ans+=sum[now.t]-sum[now.s-1];
if (now.l^now.t) big.push((data){now.s,now.l,now.t-1,query(now.l,now.t-1)});
if (now.r^now.t) big.push((data){now.s,now.t+1,now.r,query(now.t+1,now.r)});
}
return printf("%lld",ans),0;
}

Luogu P2048 [NOI2010]超级钢琴的更多相关文章

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

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

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

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

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

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

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

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

  5. LGOJ P2048 [NOI2010]超级钢琴

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

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

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

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

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

  8. P2048 [NOI2010]超级钢琴 (RMQ,堆)

    大意: 给定n元素序列a, 定义一个区间的权值为区间内所有元素和, 求前k大的长度在[L,R]范围内的区间的权值和. 固定右端点, 转为查询左端点最小的前缀和, 可以用RMQ O(1)查询. 要求的是 ...

  9. P2048 [NOI2010]超级钢琴

    传送门 考虑维护前缀和 $sum[i]$ 那么对于每一个位置 $i$ ,左端点为 $i$ 右端点在 $[i+L-1,i+R-1]$ 区间的区间最大值容易维护 维护三元组 $(o,l,r)$ ,表示左端 ...

随机推荐

  1. Android Studio 点击两次返回键,退出APP

    该功能的实现没有特别复杂,主要在onKeyDown()事件中实现,直接上代码,如下: //第一次点击事件发生的时间 private long mExitTime; /** * 点击两次返回退出app ...

  2. 常用的docker命令

    在这里记一下,以免以后忘记了. ------------------------------------------------------------------------------------ ...

  3. 洗礼灵魂,修炼python(29)--装饰器(1)—>利用经典案例解析装饰器概念

    前提必备 不急着进入正题,在前面函数作用域那一章介绍了闭包,全局变量局部变量,这里再看几个简单的闭包案例: 1):不带参数 注意: 1.这里的name属性是每个函数都有的,可以反馈函数名 2.temp ...

  4. SQLSERVER 死锁

    select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tra ...

  5. Gnome增加消息提醒extension ( Fedora 28 )

    访问 https://extensions.gnome.org/ 网站(注意:需要安装 chrome-gnome-shell  rpm 包来使得系统能与Web Browser进行通信) 安装插件: n ...

  6. nginx代理 upstream轮询

    问题描述 我有2个Tomcat  一个端口开启(8021),一个端口未开启(8022),在nginx里用upstream模块进行代理 ,代理的负载算法采用的是默认的轮询算法,配置成功后,访问页面时并没 ...

  7. Ubuntu 12.10 Tty (字符终端) 显示中文,和字体大小设置

    Tty通过修改默认的中文编码字符,和安装zhcon都无法显示中文.可安装fbterm来显示中文,命令:sudo apt-get install fbterm安装即可,进入Tty: (Ctrl+Alt+ ...

  8. node爬虫扒小说

    Step 1:  万年不变的初始化项目,安装依赖 cnpm i express cheerio superagent superagent-charset async -S express 就不用多说 ...

  9. element-ui使用导航栏跳转路由用法

    element-ui使用导航栏跳转路由用法 最近初学vue,试着做一个小项目熟悉语法与思想,其中使用elemen-ui的导航栏做路由跳转切换页面.下面记录一下学习过程 element-ui引入vue项 ...

  10. Spring集成MyBatis持久层框架

    一.MyBatis介绍 MyBatis 是一款优秀的持久层框架,它支持定制化SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集,可以使用简单的XML ...