超级钢琴题解
Posted ljk123-de-bo-ke
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超级钢琴题解相关的知识,希望对你有一定的参考价值。
超级钢琴题解
将序列之和转化为(sum[r]-sum[l-1]),固定右端点,左端取最大值
用堆丢出一个丢进两个就行了,
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+6,M=20;
int n,k,L,R,t,mi[M],lg[N],f[N][M],g[N][M],sum[N];
long long ans=0;
struct xd{
int l,r,x,y;
bool operator < (const xd &a) const {return sum[x]-sum[y-1]<sum[a.x]-sum[a.y-1];}
}tmp,nw;
priority_queue<xd> q;
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
void st(int l,int r,xd &p){
int h=lg[r-l+1]; p.l=l,p.r=r;
p.x=(f[l][h]>f[r-mi[h]+1][h]?g[l][h]:g[r-mi[h]+1][h]);
}
int main(){
n=read(),k=read(),L=read(),R=read(),mi[0]=1,lg[0]=-1;
for(int i=1;i<=n;++i) t=read(),sum[i]=sum[i-1]+t,f[i][0]=sum[i],g[i][0]=i,lg[i]=lg[i>>1]+1;
for(int i=1;i<=19;++i) mi[i]=mi[i-1]*2;
for(int i=1;i<=19;++i) for(int j=1;j+mi[i]-1<=n;++j) f[j][i]=max(f[j][i-1],f[j+mi[i-1]][i-1]),g[j][i]=(f[j][i-1]>f[j+mi[i-1]][i-1]?g[j][i-1]:g[j+mi[i-1]][i-1]);
for(int i=1;i<=n;++i) if(i+L-1<=n) st(i+L-1,min(i+R-1,n),tmp),tmp.y=i,q.push(tmp);
while(!q.empty()&&k--){
tmp=q.top(),q.pop(),ans+=1ll*(sum[tmp.x]-sum[tmp.y-1]);
if(tmp.l<=tmp.x-1) nw.y=tmp.y,st(tmp.l,tmp.x-1,nw),q.push(nw);
if(tmp.r>=tmp.x+1) nw.y=tmp.y,st(tmp.x+1,tmp.r,nw),q.push(nw);
}
printf("%lld
",ans);
return 0;
}
以上是关于超级钢琴题解的主要内容,如果未能解决你的问题,请参考以下文章