BZOJ2006:[NOI2010]超级钢琴
浅谈\(RMQ\):https://www.cnblogs.com/AKMer/p/10128219.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2006
首先,序列\([l,r]\)的和可以转化成前缀和相减:\(sum[r]-sum[l-1]\)。
其次,对于每个右端点\(pos\),有效左端点都是一段区间\([pos-r,pos-l]\)。而这里面前缀和最小的则是最优左端点。
一开始我们将所有的四元组\((v,pos,l,r)\)丢到大根堆里。这个四元组表示以\(pos\)为右端点,有效左端点区间在\([l,r]\)内,最大值为\(v\)。假设最优左端点是\(pos'\),那么对于最优解,我们只需要执行如下步骤\(k\)次即可:
取出堆顶,\(ans+=v\)。
将\((sum[pos]-query(l,pos'-1),pos,l,pos'-1)\)与\((sum[pos]-query(pos'+1,r),pos,pos'+1,r)\)放回堆里。这样可以保证\([pos',pos]\)不会再被取出。
\(query(l,r)\)表示求区间\([l,r]\)的前缀和最小值。这样,问题就得到了完美解决。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(nlogn)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll ans;
int n,limit,L,R;
int a[maxn],Log[maxn],f[20][maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct node {
int v,pos,l,r;
node() {}
node(int _v,int _pos,int _l,int _r) {
v=_v,pos=_pos,l=_l,r=_r;
}
bool operator<(const node &a)const {
return v<a.v;
}
};
struct Heap {
int tot;
node tree[maxn<<1];
void ins(node a) {
tree[++tot]=a;
int pos=tot;
while(pos>1) {
if(tree[pos>>1]<tree[pos])
swap(tree[pos>>1],tree[pos]),pos>>=1;
else break;
}
}
node pop() {
node res=tree[1];
tree[1]=tree[tot--];
int pos=1,son=2;
while(son<=tot) {
if(son<tot&&tree[son]<tree[son|1])son|=1;
if(tree[pos]<tree[son])
swap(tree[pos],tree[son]),pos=son,son=pos<<1;
else break;
}
return res;
}
}T;//手写堆carry你进第一版,值得拥有!
int fake(int num1,int num2) {
if(a[num1]<a[num2])return num1;
return num2;
}
int query(int l,int r) {
int x=Log[r-l+1];
return fake(f[x][l],f[x][r-(1<<x)+1]);
}
int main() {
n=read(),limit=read();
L=read(),R=read();Log[0]=-1;
for(int i=1;i<=n;i++) {
f[0][i]=i;
Log[i]=Log[i>>1]+1;
a[i]=read()+a[i-1];
}
for(int i=1;i<=19;i++)
for(int j=0;j+(1<<i)-1<=n;j++)
f[i][j]=fake(f[i-1][j],f[i-1][j+(1<<(i-1))]);
for(int i=L;i<=n;i++) {
int l=max(0,i-R),r=i-L;
T.ins(node(a[i]-a[query(l,r)],i,l,r));
}
for(int i=1;i<=limit;i++) {
node tmp=T.pop();
ans+=tmp.v;
int pos=query(tmp.l,tmp.r);
if(pos-1>=tmp.l)
T.ins(node(a[tmp.pos]-a[query(tmp.l,pos-1)],tmp.pos,tmp.l,pos-1));
if(pos+1<=tmp.r)
T.ins(node(a[tmp.pos]-a[query(pos+1,tmp.r)],tmp.pos,pos+1,tmp.r));
}
printf("%lld\n",ans);
return 0;
}
BZOJ2006:[NOI2010]超级钢琴的更多相关文章
- bzoj2006 [NOI2010]超级钢琴 (及其拓展)
bzoj2006 [NOI2010]超级钢琴 给定一个序列,求长度在 \([L,\ R]\) 之间的区间和的前 \(k\) 大之和 \(n\leq5\times10^5,\ k\leq2\times1 ...
- bzoj千题计划162:bzoj2006: [NOI2010]超级钢琴
http://www.lydsy.com/JudgeOnline/problem.php?id=2006 输出最大的k个 sum[r]-sum[l-1] (L<=r-l+1<=R) 之和 ...
- BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MB Submit: 3446 Solved: 1692 [Submit][Sta ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 3591 Solved: 1780[Submit][Statu ...
- bzoj2006 noi2010 超级钢琴 主席树 + 优先队列
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2435 Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送 ...
- BZOJ2006[NOI2010]超级钢琴——堆+主席树
题目描述 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中 ...
- 【贪心 计数】bzoj2006: [NOI2010]超级钢琴
这么经典的贪心我怎么现在才做啊…… Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个 ...
- BZOJ2006——[NOI2010]超级钢琴
1.题意:给一个序列,让你取出k个不同的区间,要求长度在之间,问所有区间和的最大值 2.分析:这道题拿过来就能知道是要拿出前k个最大的区间,我们思考最暴力的做法,就是把这个所有的区间枚举出来算,取出前 ...
- bzoj2006: [NOI2010]超级钢琴
题意:给一个序列(n<=500000),要求选定k个不同区间,使得区间长度在L,R之间,并使得k个区间和之和最大,输出这个最大值. 刚拿到题的时候想的是,对于每个点,如果以它开头,那么之后的L- ...
随机推荐
- session 的工作原理以及使用细节和url编码
/**********************************************模拟页面************************************************* ...
- null的比较问题
select count(*) from table_a WHERE status=1 and end_time<now(); 写这个sql的时候有点纠结,万一end_time是null怎么办 ...
- 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- go web的简单服务器
1)简单web服务器: package main import ( "fmt" "net/http" ) func sayHelloName(w http.Re ...
- java 面试总结
1.static变量与实体变量的差别? static是静态变量,static能够通过类名直接訪问 内存方面的不同:static在定义的时候jvm就会分配空间, 而实体变量仅仅有在创建对象的时候才会去分 ...
- UIScrollView奇葩不滑动
首先要说声尼玛,真奇葩,从来都没有遇到过这个问题,首先描述一下背景: 我是用XIB拖拽了一个UIScrollView在View上,然后设置了frame,在ViewDidLoad里面,设置了scroll ...
- 【转】soapUI和Jmeter的接口测试结构区别
使用SoapUI和Jmeter都可以进行自动化接口测试,但是每个工具都有自身的特点,所以他们的结构也有一定的区别 SoapUI 项目名称 -Rest服务.Rest资源 在使用SoapUI进行接口测试时 ...
- vscode设置默认shell 快速到行
vscode设置默认shell - CSDN博客 https://blog.csdn.net/butterfly5211314/article/details/78944805 在文件 -> 首 ...
- div+css清除浮动代码
<style type="text/css"> .div1{ background:#000080; border:1px solid red;} .div2{ bac ...
- Linux PPTP拨号
试验环境:Linux marsboard 3.4.90 #9 SMP PREEMPT Thu Mar 3 18:28:43 CST 2016 armv7l armv7l armv7l GNU/Linu ...