[NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]
题面:
思路:
首先容易想到用堆维护的O(n2logn)暴力
那么肯定就是在这个基础上套数据结构了【愉快】
然而我因为过于蒟蒻......只想得到主席树暴力***过去的方法
大概就是把前缀和算出来,然后放到一棵线段树里面
对于每一个i(i=1...(n-L+1)),线段树查询以i为左端点的所有区间右端点中,前缀和最大的一个
因为区间[i,j]可以变成pre[j]-pre[i]的形式,那么只需要最大化pre[j]就可以了
一开始,对于所有的i把这个最大值求出来,减掉pre[i-1],再放到堆里面
每次从堆顶取出当前最大值,然后答案加上这个值,同时主席树上修改一波,把这个点在树上的值改成-inf
其实一共有n棵主席树,只不过每一棵都公用同一个初始树,后面每次修改又只会新开logn的节点,所以总空间复杂度应该是O(nlogn+klogn)的
就这样,总时间复杂度O(nlogn+klogn),常数略大
然而,菊苣们早已开发出了新的希望算法,那就是查询O(1)的ST表
把上文中的初始询问(n个,在初始线段树上的那些)转化成三元组(i,L,R),代表左端点是i的,长度在[L,R]之内的序列最大值
那么,每次堆顶弹出以后,可以这样操作:
设堆顶元素为x,我们新建两个三元组(i,L,x-1)(i,x+1,R),把这两个三元组的值求出来放到堆里面去即可
效率虽然还是O(nlogn+klogn),但是常数比我的算法不知道高到哪里去了,跑的贼快
Code:
不知道为什么,500000的点需要开两千五百万的数组......连续3次RE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 1e15
#define ll long long
using namespace std;
inline int read(){
int re=,flag=;char ch=getchar();
while(ch>''||ch<''){
if(ch=='-') flag=-;
ch=getchar();
}
while(ch>=''&&ch<='') re=(re<<)+(re<<)+ch-'',ch=getchar();
return re*flag;
}
struct node{
ll w;int pos;
bool operator <(const node &b){
return w<b.w;
}
}a[];
struct NODE{
ll w;int pos1,pos2;
bool operator <(const NODE &b)const{
return w<b.w;
}
};
int n,m,L,R,x[];
int ch[][],cnt,root[];ll pre[];
priority_queue<NODE>q;
void update(int x){
if(a[ch[x][]].w>=a[ch[x][]].w) a[x].w=a[ch[x][]].w,a[x].pos=a[ch[x][]].pos;
else a[x].w=a[ch[x][]].w,a[x].pos=a[ch[x][]].pos;
}
int build(int l,int r){
int mid=(l+r)>>,cur=++cnt;
if(l==r){
a[cur].w=pre[l];a[cur].pos=l;return cur;
}
ch[cur][]=build(l,mid);ch[cur][]=build(mid+,r);
update(cur);
return cur;
}
node max(node l,node r){
return l<r?r:l;
}
node query(int l,int r,int ql,int qr,int cur){
int mid=(l+r)>>;node re=(node){-inf,};
if(l>=ql&&r<=qr) return a[cur];
if(mid>=ql) re=max(re,query(l,mid,ql,qr,ch[cur][]));
if(mid<qr) re=max(re,query(mid+,r,ql,qr,ch[cur][]));
return re;
}
int change(int l,int r,int u,int his){
int mid=(l+r)>>,cur=++cnt;
if(l==r){
a[cur]=(node){-inf,l};return cur;
}
if(u<=mid) ch[cur][]=ch[his][],ch[cur][]=change(l,mid,u,ch[his][]);
else ch[cur][]=ch[his][],ch[cur][]=change(mid+,r,u,ch[his][]);
update(cur);return cur;
}
int main(){
freopen("piano.in","r",stdin);
freopen("piano.out","w",stdout);
int i,t1;ll ans=;node tmp;NODE tt;
n=read();m=read();L=read();R=read();
for(i=;i<=n;i++) x[i]=read(),pre[i]=pre[i-]+(ll)x[i];
t1=build(,n);
for(i=;i<=n-L+;i++){
root[i]=t1;tmp=query(,n,min(n,i+L-),min(n,i+R-),t1);
q.push((NODE){-pre[i-]+tmp.w,i,tmp.pos});
}
for(i=;i<=m;i++){
ans+=q.top().w;tt=q.top();q.pop();
root[tt.pos1]=change(,n,tt.pos2,root[tt.pos1]);
tmp=query(,n,min(n,tt.pos1+L-),min(n,tt.pos1+R-),root[tt.pos1]);
q.push((NODE){-pre[tt.pos1-]+tmp.w,tt.pos1,tmp.pos});
}
printf("%lld\n",ans);
}
[NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]的更多相关文章
- bzoj2006 noi2010 超级钢琴 主席树 + 优先队列
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2435 Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送 ...
- [BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 3591 Solved: 1780[Submit][Statu ...
- [NOI2010]超级钢琴 主席树
[NOI2010]超级钢琴 链接 luogu 思路 和12省联考的异或粽子一样. 堆维护n个左端点,每次取出来再放回去次 代码 #include <bits/stdc++.h> #defi ...
- BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)
题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...
- [HEOI2016] 字符串 - 后缀数组,主席树,ST表,二分
[HEOI2016] 字符串 Description 给定一个字符串 \(S\), 有 \(m\) 个询问,每个询问给定参数 \((a,b,c,d)\) ,求 \(s[a..b]\) 的子串与 \(s ...
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)
[BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...
- 题解 【NOI2010】超级钢琴
[NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
随机推荐
- Airflow 调度基础
1. Airflow Airflow是一个调度.监控工作流的平台.用于将一个工作流制定为一组任务的有向无环图(DAG),并指派到一组计算节点上,根据相互之间的依赖关系,有序执行. 2. 安装 pip安 ...
- 国外常用代理IP对比【仅供参考】
国外常用代理IP对比[仅供参考]http://www.it588.cn/vmware/2019-03-22/547.html
- 删除临时文件的bat文件
@echo offecho 正在清除系统垃圾文件,请稍等......del /f /s /q %systemdrive%\*.tmpdel /f /s /q %systemdrive%\*._mpde ...
- python_76_json与pickle反序列化2
import pickle def say(name):#序列化时用完会释放,要想反序列化,要重新写上该函数,否则会出错 print('我的高中:', name)#可以和之前的序列化函数不同 f=op ...
- Python02 变量
变量 因为Python是弱变量类型编程语言,所以变量赋值不需要类型声明. 每个变量在内存中创建,都包括变量的标识,名称和数据这些信息. 每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 变量 ...
- GIT 团队协作快速入门使用
GIT使用: 1.本地新建一个文件夹 git init 2.克隆远程仓库 git clone git@xxxxx.git 3.本地创建一个dev分支 (前提是服务器端已经创建好有 DEV 分支) gi ...
- js控制台输出图案
控制台输出图案 console.log([ " _ooOoo_", " o8888888o", " 88\" . \"88&quo ...
- vue购物车的实现
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Tempter of the Bone HDU - 1010(dfs)
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- JQ剪辑图片插件,适用于移动端和PC端
主要用到以下JS文件: <script src="js/photo/iscroll-zoom.js"></script> <script src=&q ...