超级钢琴

知识储备

在做这道题前,我们先要了解一下ST表(一种离线求区间最值的方法)

ST表使用DP实现的,其查询复杂度为O(1).

那么我们怎么用DP实现呢??

首先,我们设立一个状态f[i][j],其中i代表起点(包括在内),而j则代表是2的几次方,那么这个状态的含义就是以i为起点,求i~i+2^j-1内的区间最大值

最开始,我们定义f[i][0]的值为其本身即a[i]

那么我们转移方程就是

f[i][j]=max(f[i][j-1],f[i+(1<<(j-1)][j-1]);  //一层一层的推过来...

然后我们就知道在一定区间内的最大值了!!

查询也是一个需要特别注意的点,我们要知道查询的x位置和y位置之间max,就要知道y-x+1是y的几次方,其中这个要向下取整,防止越界,但是这样我们就会有一部分扫不到,由于我们向下取整的这个区间是大于等于这个区间的一半的,所以我们可以反过来,从y-(1<<k)到y,这样可以保证不会漏掉数据,并且重复的话也不会对答案产生影响

但是注意!!算k的式子要小心啊

别取错了,一个小BUG就会导致你WA掉...

#include<bits/stdc++.h>
#define ll long long
#define FOR(i,a,b) for(register int i=a;i<=b;i++)
#define ROF(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
const int N=+;
int n,m;
int a[N];
int f[N][];
int scan()
{
int as=,f=;
char c=getchar();
while(c>''||c<''){if(c=='-') f=-;c=getchar();}
while(c>=''&&c<=''){as=(as<<)+(as<<)+c-'';c=getchar();}
return as*f;
}
void RMQ(int n)
{
FOR(i,,)
{
FOR(j,,n)
{
if(j+(<<i)-<=n)
f[j][i]=max(f[j][i-],f[j+(<<(i-))][i-]);
}
}
}
int main()
{
n=scan();
m=scan();
FOR(i,,n)
a[i]=scan(),f[i][]=a[i];
RMQ(n);
FOR(i,,m)
{
int x,y;
x=scan();
y=scan();
int k=(int)(log((double)(y-x+))/log(2.0));
printf("%d\n",max(f[x][k],f[y-(<<k)+][k]));
}
return ;
}

代码戳这里


接下来我们要讲正事了!!

我们的目光转到钢琴这一题上

思路

首先,我们前缀和储存值,然后在用KMQ,将一些区间内的max求出来

然后我们根据题目要求,由于题目要我们求最大权值,那么我们就求每个可能区间里面的max,将其储存在堆里面.

但是最开始的时候,我们只求出了以某一点为起点的最大值,但是我们最后要求的1~k个最大值的相加

所以我们在每取出一个max是,再去寻找以该点为起点的max,只不过此时的max不是当前的最有解,而是次优解,但是也可能成为新的最有解,

然后题目打这里就差不多啦

#include<bits/stdc++.h>
#define ll long long
#define gc getchar()
#define FOR(i,a,b) for(register int i=a;i<=b;i++)
#define ROF(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
const int N=+;
int n,m,L,R;
ll sum[N];
int id[N][],f[N][];
ll ans=;
int scan()
{
int as=,f=;char c=gc;
while(c>''||c<''){if(c=='-') f=-;c=gc;}
while(c>=''&&c<=''){as=(as<<)+(as<<)+c-'';c=gc;}
return as*f;
}
//learn new
struct s1
{
int u,l,r,pos;
bool operator <(s1 y) const
{
return sum[pos]-sum[u-]<sum[y.pos]-sum[y.u-];//大的放队尾
}
}tmp;
priority_queue<s1>q;//队列
void init(int &pos,int l,int r)
{
int j=log2(r-l+);
if(f[l][j]>f[r-(<<j)+][j]) pos=id[l][j];
else pos=id[r-(<<j)+][j];
}//这里都懂吧,KMQ的查询
int main()
{
n=scan();m=scan();L=scan();R=scan();
FOR(i,,n)
{
sum[i]=scan();sum[i]+=sum[i-];//前缀和
f[i][]=sum[i];
id[i][]=i;//位置的处理
}
FOR(j,,)
{
FOR(i,,n)
{
if(i+(<<j)->n) break;
if(f[i][j-]>f[i+(<<(j-))][j-]) f[i][j]=f[i][j-],id[i][j]=id[i][j-];
else f[i][j]=f[i+(<<(j-))][j-],id[i][j]=id[i+(<<(j-))][j-];
}//这里其实就是KMQQAQ
}
FOR(i,,n-L+)//入坑silasila......
{
int l=i+L-; int r=min(i+R-,n),pos=,u=i;//随便给pos一个值
init(pos,l,r);//pos在这里赋好了值
tmp=(s1){u,l,r,pos};//然后加入四元组吧..
q.push(tmp);//入队
}
while(m--)
{
tmp=q.top(); q.pop();//弹出顶端,即最优解
int u=tmp.u,l=tmp.l,r=tmp.r,tps=tmp.pos,pos=tmp.pos;//去寻找次
//优解
ans+=sum[tps]-sum[u-];
if(tps>l)
{
init(pos,l,tps-);tmp=(s1){u,l,tps-,pos};q.push(tmp);
}
if(tps<r)
{
init(pos,tps+,r);tmp=(s1){u,tps+,r,pos};q.push(tmp);
}
}
printf("%lld",ans);
return ;
}

代码戳这里

Sequence(ST表)(洛谷P2048)的更多相关文章

  1. 【模板】ST表 洛谷P1816 忠诚

    P1816 忠诚 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于 管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨, ...

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

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

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

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

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

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

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

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

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

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

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

  8. 【洛谷3865】 【模板】ST表(猫树)

    传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里

  9. 【洛谷】P2880 [USACO07JAN]平衡的阵容Balanced Lineup(st表)

    题目背景 题目描述: 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连 ...

随机推荐

  1. c++返回引用

    #include <iostream> #include <ctime> using namespace std; double vals[] = {10.1, 12.6, 3 ...

  2. 推荐5个机器学习Python 库,国内外评价超高

    机器学习令人无比神往,但从事这个工作的人可能并不这么想. 机器学习的工作内容往往复杂枯燥又困难——通过大量重复工作进行提升必不可少: 汇总工作流及传输渠道.设置数据源以及在内部部署和云部署的资源之间来 ...

  3. CCF-NOIP-2018 提高组(复赛) 模拟试题(四)

    T1 贪吃蛇 [问题描述] 贪吃蛇是一个好玩的游戏.在本题中,你需要对这个游戏进行模拟. 这个游戏在一个 \(n\) 行 \(m\) 列的二维棋盘上进行. 我们用 \((x, y)\) 来表示第 \( ...

  4. Java IO学习--RandomAccessFile

    1.什么是 随机访问文件流 RandomAccessFile 这个类在很多资料上翻译成中文都是:随机访问文件,在中文里,随机是具有不确定的含义,指一会访问这里,一会访问那里的意思.如果以这种语义来解释 ...

  5. 关于2018年东南大学Robomaster算法组工作的总结

    笔者在写作时,为东南大学机器人俱乐部下Robomaster大赛SUPER NOVA战队算法组的负责人之一(这名字写起来好长).而SUPER NOVA战队则于2018年5月19日正式结束了中部分区赛,获 ...

  6. Android之内容提供者ContentProvider的总结

    本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 Conte ...

  7. 软件工程项目组Z.XML会议记录 2013/09/25

    软件工程项目组Z.XML会议记录 [例会时间]2013年9月25日周三21:30-22:10 [例会形式]小组讨论 [例会地点]三号公寓楼会客厅 [例会主持]李孟 [会议记录]肖俊鹏 会议整体流程 签 ...

  8. Uva 1590 IP Networks

    这道题目是一道关于IP地址的题目,要深入理解这道题需要有一定的网络基础. 这道题目我第一次做的时候虽然也AC了,但代码写的比较复杂,不够精炼.近期刚刚参加了网络方面的培训,在有一定知识的基础上,又重写 ...

  9. Luogu3953 NOIP2017逛公园(最短路+拓扑排序+动态规划)

    跑一遍dij根据最短路DAG进行拓扑排序,按拓扑序dp即可.wa了三发感觉非常凉. #include<iostream> #include<cstdio> #include&l ...

  10. P4016 负载平衡问题

    题目描述 G 公司有 n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入输出格式 输入格式: 文 ...