优先队列+st
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int INF=1E9;
const int maxn=5e5+10;
int n,k,minlen,maxlen;
ll a[maxn],sum[maxn];
int st[maxn][20],idx[maxn][20];
void initst()
{
for(int i=1;i<=n;i++)
{
st[i][0]=sum[i];
idx[i][0]=i;
}
for(int j=1;j<=20;j++)
{
for(int i=1;i<=n;i++)
{
if(i+(1<<j)-1<=n)
{
if(st[i][j-1]>st[i+(1<<j-1)][j-1])
{
st[i][j]=st[i][j-1];
idx[i][j]=idx[i][j-1];
}else{
st[i][j]=st[i+(1<<j-1)][j-1];
idx[i][j]=idx[i+(1<<j-1)][j-1];
}
}
}
}
}
int query(int a,int b)
{
int k=log(b-a+1)/log(2);
return max(st[a][k],st[b-(1<<k)+1][k]);
}
int query_IDX(int a,int b)
{
int k=log(b-a+1)/log(2);
if(st[a][k]>st[b-(1<<k)+1][k])return idx[a][k];
else return idx[b-(1<<k)+1][k];
}
struct node{
int i,IDX,l,r,v;
node(){}
node(int a,int b,int c,int d,int e)
: i(a),IDX(b),l(c),r(d),v(e){}
bool operator <(const node& b)const {
return v<b.v;
}
};
priority_queue<node> q;
int main()
{
scanf("%d%d%d%d",&n,&k,&minlen,&maxlen);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
initst();
for(int i=1;i+minlen-1<=n;i++)
{
int l=i+minlen-1;
int r=min(i+maxlen-1,n);
int v=query(l,r);
int IDX=query_IDX(l,r);
q.push(node(i,IDX,l,r,v-sum[i-1]));
}
ll ans=0;
while(k--)
{
node cur=q.top();
q.pop();
ans+=cur.v;
if(cur.IDX>cur.l)
{
int l=cur.l;
int r=cur.IDX-1;
int v=query(l,r);
int IDX=query_IDX(l,r);
q.push(node(cur.i,IDX,l,r,v-sum[cur.i-1]));
}
if(cur.IDX<cur.r)
{
int l=cur.IDX+1;
int r=cur.r;
int v=query(l,r);
int IDX=query_IDX(l,r);
q.push(node(cur.i,IDX,l,r,v-sum[cur.i-1]));
}
}
printf("%lld\n",ans);
return 0;
}