我们定义$(p,l,r)=max{sum[t]-sum[p-1],p+l-1leq tleq p+r-1 }$
那么因为对每一个$p$来说$sum[p-1]$是一个定值,所以我们只要在$[p+l-1,p+r-1]$的区间里找出最大的$sum[t]$就行了,这就是一个RMQ问题,开个ST表就行了
一开始我们用优先队列存储所有的$(p,l,r)$,然后每一次取出队首更新答案
注意如果$t$被选了,答案还有可能在$t$两边的区间里,所以记得把$(p,l,t-1)$和$(p,t+1,r)$给扔进优先队列里
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<queue> 7 #include<cmath> 8 #define ll long long 9 using namespace std; 10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 11 char buf[1<<21],*p1=buf,*p2=buf; 12 inline int read(){ 13 #define num ch-'0' 14 char ch;bool flag=0;int res; 15 while(!isdigit(ch=getc())) 16 (ch=='-')&&(flag=true); 17 for(res=num;isdigit(ch=getc());res=res*10+num); 18 (flag)&&(res=-res); 19 #undef num 20 return res; 21 } 22 const int N=500005,LOG=20; 23 ll sum[N],st[N][LOG]; 24 int n,k,l,r; 25 void init(){ 26 for(int i=1;i<=n;++i) st[i][0]=i; 27 for(int j=1;(1<<j)<=n;++j) 28 for(int i=1;i+(1<<j)-1<=n;++i){ 29 int x=st[i][j-1],y=st[i+(1<<j-1)][j-1]; 30 st[i][j]=sum[x]>sum[y]?x:y; 31 } 32 } 33 inline int query(int l,int r){ 34 int k=log2(r-l+1); 35 int x=st[l][k],y=st[r-(1<<k)+1][k]; 36 return sum[x]>sum[y]?x:y; 37 } 38 struct node{ 39 int p,l,r,t; 40 node(){} 41 node(int p,int l,int r):p(p),l(l),r(r),t(query(l,r)){} 42 inline bool operator <(const node &b)const 43 {return sum[t]-sum[p-1]<sum[b.t]-sum[b.p-1];} 44 }; 45 priority_queue<node> q; 46 int main(){ 47 // freopen("testdata.in","r",stdin); 48 n=read(),k=read(),l=read(),r=read(); 49 for(int i=1;i<=n;++i) 50 sum[i]=read(),sum[i]+=sum[i-1]; 51 init(); 52 for(int i=1;i<=n;++i) 53 if(i+l-1<=n) 54 q.push(node(i,i+l-1,min(i+r-1,n))); 55 ll ans=0; 56 while(k--){ 57 int p=q.top().p,l=q.top().l,r=q.top().r,t=q.top().t; 58 q.pop(); 59 ans+=sum[t]-sum[p-1]; 60 if(l!=t) q.push(node(p,l,t-1)); 61 if(t!=r) q.push(node(p,t+1,r)); 62 } 63 printf("%lld ",ans); 64 return 0; 65 }