由于他已经把顺序给排好了,一开始以为是乱序然后要你找。。。。。。。既然顺序已经排好了,值一开始又都大于0,那么题目就变成了找k个不同的连续子串,使得和最大。
所以一开始把所有长度为l的丢进堆里,每次把值最大的取出来再分裂。
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
#define maxn 600000
#define mp make_pair
#define ft first
#define sd second
#define pii pair<int,int>
int c[maxn],s[maxn],f[maxn][20],g[maxn][20];
struct node
{
int h,v,l,r,id;
void in(int a,int b,int c,int d,int e)
{
h=a;l=b;r=c;id=d;v=e;
}
friend bool operator <(node aa,node bb)
{
return aa.v<bb.v;
}
};
priority_queue<node>q;
int n,m,k,L,R;
void getf()
{
for(int i=1;i<=n;i++)
f[i][0]=s[i],g[i][0]=i;
m=(int)(log(double(n))/log(2.0) );
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n-(1<<i)+1;j++)
{
if(f[j][i-1]>f[j+(1<<(i-1))][i-1])
{
f[j][i]=f[j][i-1];
g[j][i]=g[j][i-1];
}
else
{
f[j][i]=f[j+(1<<(i-1))][i-1];
g[j][i]=g[j+(1<<(i-1))][i-1];
}
}
}
}
pii query(int l,int r)
{
int t=(int)(log((double)r-l+1)/log(2.0));
pii tmp;
if(f[l][t] > f[r-(1<<t)+1][t] ) tmp=mp(g[l][t],f[l][t]);
else tmp=mp(g[r-(1<<t)+1][t],f[r-(1<<t)+1][t]);
return tmp;
}
void solve()
{
getf();
int l,r,id,val;
node kk;
for(int i=1;i<=n;i++)
{
if(i+L-1>n) break;
l=i+L-1;
r=min(i+R-1,n);
pii tmp=query(l,r);
id=tmp.ft;
val=tmp.sd;
kk.in(i,l,r,id,val-s[i-1]);
q.push(kk);
}
long long ans=0;
node tt;
for(int i=1;i<=k;i++)
{
kk=q.top();
q.pop();
ans+=kk.v;
if(kk.id-1>=kk.l)
{
pii tmp=query(kk.l,kk.id-1);
tt.in( kk.h, kk.l, kk.id-1, tmp.ft, tmp.sd-s[kk.h-1] );
q.push(tt);
}
if(kk.id+1<=kk.r)
{
pii tmp=query(kk.id+1,kk.r);
tt.in( kk.h, kk.id+1, kk.r, tmp.ft, tmp.sd-s[kk.h-1] );
q.push(tt);
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d%d%d%d",&n,&k,&L,&R);
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
s[i]=s[i-1]+c[i];
}
solve();
//system("pause");
return 0;
}