bzoj 2006 [NOI2010]超级钢琴——ST表+堆
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2006
每个右端点的左端点在一个区间内;用堆记录端点位置、可选区间,按价值排序;拿出一个后也许分裂成两个。
第一次写了ST表,写得巨复杂,记录向前/后的最小值和位置,还为了预处理,又记 2^j 走到哪;调了半天边界,最后发现是Lg写错了!至今仍不知那样写为什么会错……
看看别人的代码,原来不用记两个方向的,用的时候往前跳几步再用向后的就行!也不用记录最小值,只要记录位置就行了;也不用记录 to[ ][ ] ,只要从 i+2^j 有没有超过n就能判断边界。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=5e5+,Lm=;
int n,m,L,R,a[N],s[N],Lg[N],stp[N][Lm+],stn[N][Lm+],to[N][Lm+];
int idp[N][Lm+],idn[N][Lm+];
ll ans;
struct Node{
int ps,to,l,r,v;
Node(int p,int t,int l,int r,int v):ps(p),to(t),l(l),r(r),v(v) {}
bool operator< (const Node &b) const
{return v<b.v;}
};
priority_queue<Node> q;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return fx?ret:-ret;
}
void init()
{
/*
int i=1,cd=0,nxt;
for(;i<=n;i=nxt,cd++)
{
nxt=i<<1;
for(int j=i;j<nxt&&j<=n;j++) Lg[j]=cd;
}
i>>=1;
for(;i<=n;i++) Lg[i]=cd;
*/
for(int i=;i<=n;i++) Lg[i]=Lg[i>>]+; memset(to,0x3f,sizeof to);//
for(int i=;i<n;i++)
{
stp[i][]=s[i]; idp[i][]=i;
to[i][]=i-;
for(int j=,d;j<=Lm;j++)
{
d=to[i][j-];
if(d<||to[d][j-]>n)break;// >n!!! //if d<0
to[i][j]=to[d][j-];
if(stp[d][j-]<stp[i][j-])
{
stp[i][j]=stp[d][j-]; idp[i][j]=idp[d][j-];
}
else
{
stp[i][j]=stp[i][j-]; idp[i][j]=idp[i][j-];
}
}
}
memset(to,0x3f,sizeof to);
for(int i=n-;i>=;i--)
{
stn[i][]=s[i]; idn[i][]=i;
to[i][]=i+;
for(int j=,d;j<=Lm;j++)
{
d=to[i][j-];
if(to[d][j-]>n)break;
to[i][j]=to[d][j-];
if(stn[d][j-]<stn[i][j-])
{
stn[i][j]=stn[d][j-]; idn[i][j]=idn[d][j-];
}
else
{
stn[i][j]=stn[i][j-]; idn[i][j]=idn[i][j-];
}
}
}
}
int main()
{
n=rdn(); m=rdn(); L=rdn(); R=rdn();
for(int i=;i<=n;i++) a[i]=rdn(),s[i]=s[i-]+a[i];
init();
for(int i=,d,t;i<=n;i++)
{
int l=i-R,r=i-L;//not +1
if(r<) continue; l=max(l,);
t=Lg[r-l+];//not +1
d=(stp[r][t]<stn[l][t]?idp[r][t]:idn[l][t]);
q.push(Node(i,d,l,r,s[i]-s[d]));
} while(m--)
{
Node k=q.top(); q.pop(); ans+=k.v;
int l1=k.l,r1=k.to-, l2=k.to+,r2=k.r;
int t,d;
if(l1<=r1)
{
t=Lg[r1-l1+];
d=(stp[r1][t]<stn[l1][t]?idp[r1][t]:idn[l1][t]);
q.push(Node(k.ps,d,l1,r1,s[k.ps]-s[d]));
} if(l2<=r2)
{
t=Lg[r2-l2+];
d=(stp[r2][t]<stn[l2][t]?idp[r2][t]:idn[l2][t]);
q.push(Node(k.ps,d,l2,r2,s[k.ps]-s[d]));
}
}
printf("%lld\n",ans);
return ;
}
bzoj 2006 [NOI2010]超级钢琴——ST表+堆的更多相关文章
- BZOJ 2006: [NOI2010]超级钢琴 ST表+堆
开始想到了一个二分+主席树的 $O(n\log^2 n)$ 的做法. 能过,但是太无脑了. 看了一下题解,有一个 ST 表+堆的优美解法. 你发现肯定是选取前 k 大最优. 然后第一次选的话直接选固定 ...
- BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]
题意: 一个序列,求k个不相同的长度属于\([L,R]\)的区间使得和最大 前缀和,对于每个r找最小的a[l] 然后我yy了一个可持久化线段树做法...也许会T 实际上主席树就可以了,区间k小值 然后 ...
- [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3679 Solved: 1828[Submit][Statu ...
- 【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
[BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以 ...
- BZOJ 2006 NOI2010 超级钢琴 划分树+堆
题目大意:给定一个序列.找到k个长度在[l,r]之间的序列.使得和最大 暴力O(n^2logn),肯定过不去 看到这题的第一眼我OTZ了一下午... 后来研究了非常久别人的题解才弄明确怎么回事...蒟 ...
- Bzoj 2006: [NOI2010]超级钢琴 堆,ST表
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2222 Solved: 1082[Submit][Statu ...
- BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )
取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<c ...
- 【BZOJ-2006】超级钢琴 ST表 + 堆 (一类经典问题)
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2473 Solved: 1211[Submit][Statu ...
- BZOJ 2006: [NOI2010]超级钢琴
2006: [NOI2010]超级钢琴 Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 2613 Solved: 1297[Submit][Statu ...
随机推荐
- [Hibernate开发之路](3)基础配置
一 JDBC链接 通常你希望SessionFactory来为你创建和缓存(pool)JDBC连接. 假设你採用这样的方式, 仅仅须要例如以下例所看到的那样,打开一个Session: Session s ...
- 解决Gradle执行命令时报Could not determine the dependencies of task ':compileReleaseJava'.
Could not determine the dependencies of task ':compileReleaseJava'. > failed to find target andro ...
- sql的一些知识_函数_汇总数据
汇总数据 avg()---------求平均数 值得注意的是:avg()只能用于一个列的平均值查询,多个列的平均值请使用多个avg() avg()忽略null值 count()-------计数(指定 ...
- webstorm中使用java的块凝视
webstorm中使用java的块凝视 有图有真相 使用java中非常方便得/**+enter就能高速创建类凝视.可是webstrom中没有现成的,所以我们得自己去创建一个,详细方法例如以下: 博主w ...
- js动态函数
最近项目中使用百度模板引擎baiduTemplate.js,使用动态函数解析模板中代码. 通过new Function([arg1,arg2,...,argN,]functionBody)方式实现动态 ...
- 【转】VMware 11.0 简体中文版|附永久密钥
VMware 11.0 简体中文版|附永久密钥 昨天,VMware虚拟机11.0 简体中文版正式发布,值得注意的是新版抛弃了32位系统支持,安装包体积大幅减小, 新增Windows 10 技术预览版支 ...
- canvas 星空插件
(function(a){ a.fn.starBg=function(p){ var p=p||{}; var w_w=p&&p.window_width?p.window_width ...
- PHP 7.1.5编译安装
1. 安装基础组件 yum install -y libxml2 libxml2-devel bzip2 bzip2-devel curl-devel libjpeg libjpeg-devel li ...
- ubuntu手机识别
1.sudo gedit /etc/udev/rules.d/51-android.rules 2.将以下内容拷贝保存 SUBSYSTEM=="usb", ATTR{idVendo ...
- python的id()函数的一个小方面(转载)
>>> a = 2 >>> b = 2 >>> id(a) 21132060 >>> id(b) 21132060 >&g ...