维护前缀和,用线段树维护距离一个点[L,R]的最大值,并记录左右区间限制,将它加入优先队列,当取出一个点时,加入[L,where-1]和[where+1,R]两个值,记录左右限制。具体细节看代码。(写的不可读QAQ)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int read()
{
char ch=getchar();int f=0,x=1;
while(ch<'0'||ch>'9'){if(ch=='-') x=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}
return f*x;
}
int n,k,tot=1,L,R,final_pla;
long long ans;
int a[500005],s[500005];
struct segtree
{
int ls;
int rs;
int maxx;
int pla;
}tree[2000005];
struct data
{
int l;
int where;
int sum;
int llimit;
int rlimit;
};
bool operator < (const data &x,const data &y)
{
return x.sum<y.sum;
}
priority_queue<data> q;
void build(int p,int l,int r)
{
int mid=l+r>>1;
if(l==r)
{
tree[p].pla=l;
tree[p].maxx=s[l];
return;
}
tree[p].ls=++tot;
tree[p].rs=++tot;
build(tree[p].ls,l,mid);
build(tree[p].rs,mid+1,r);
if(tree[tree[p].ls].maxx>tree[tree[p].rs].maxx)
{
tree[p].maxx=tree[tree[p].ls].maxx;
tree[p].pla=tree[tree[p].ls].pla;
}
else
{
tree[p].maxx=tree[tree[p].rs].maxx;
tree[p].pla=tree[tree[p].rs].pla;
}
}
int query(int p,int l,int r,int x,int y)
{
int mid=l+r>>1;
if(l==x&&r==y)
{
final_pla=tree[p].pla;
return tree[p].maxx;
}
if(y<=mid)
return query(tree[p].ls,l,mid,x,y);
else if(x>mid)
return query(tree[p].rs,mid+1,r,x,y);
else
{
int lmax=query(tree[p].ls,l,mid,x,mid),lpla=final_pla;
int rmax=query(tree[p].rs,mid+1,r,mid+1,y),rpla=final_pla;
if(lmax>rmax)
{
final_pla=lpla;
return lmax;
}
else
{
final_pla=rpla;
return rmax;
}
}
}
int main()
{
n=read(),k=read();L=read(),R=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
}
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+a[i];
}
build(1,1,n);
for(int i=1;i+L-1<=n;i++)
{
data temp;
temp.l=i;
temp.sum=query(1,1,n,min(i+L-1,n),min(i+R-1,n))-s[i-1];
temp.where=final_pla;
temp.llimit=min(i+L-1,n);
temp.rlimit=min(i+R-1,n);
q.push(temp);
}
for(int i=1;i<=k;i++)
{
data temp,temp1,temp2;
temp=q.top();
q.pop();
ans+=temp.sum;
temp1.l=temp2.l=temp.l;
if(temp.where!=temp.llimit)
{
temp1.sum=query(1,1,n,temp.llimit,temp.where-1)-s[temp.l-1];
temp1.where=final_pla;
temp1.llimit=temp.llimit;
temp1.rlimit=temp.where-1;
q.push(temp1);
}
if(temp.where!=temp.rlimit)
{
temp2.sum=query(1,1,n,temp.where+1,temp.rlimit)-s[temp.l-1];
temp2.where=final_pla;
temp2.rlimit=temp.rlimit;
temp2.llimit=temp.where+1;
q.push(temp2);
}
}
cout<<ans;
}