码迷,mamicode.com
首页 > 其他好文 > 详细

超级钢琴题解

时间:2019-10-20 19:59:46      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:int   ==   getch   print   ++i   return   cpp   转化   lin   

超级钢琴题解

将序列之和转化为\(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\n",ans);
    return 0;
} 

超级钢琴题解

标签:int   ==   getch   print   ++i   return   cpp   转化   lin   

原文地址:https://www.cnblogs.com/ljk123-de-bo-ke/p/11708660.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!