题面大意:给定长为 n n n的序列,求长度在 [ L , R ] [L,R] [L,R]区间和前 k k k大子区间之和
首先区间和我们可以转换成前缀和之差
即
s
u
m
[
l
,
r
]
=
s
[
r
]
−
s
[
l
−
1
]
sum[l,r]=s[r]-s[l-1]
sum[l,r]=s[r]−s[l−1]
暴力的做法是先枚举左端点 l l l,然后暴力枚举长度合法的区间对应的右端点 r r r,找出这些区间和,然后取出前 k k k大
显然过不了是吧……
别急,我们再来看一下刚才这个暴力的思路
a n s = ∑ ( s [ r ] − s [ l − 1 ] ) ( 1 ≤ l ≤ r ≤ n ) ans=\sum(s[r]-s[l-1])(1\leq l \leq r \leq n) ans=∑(s[r]−s[l−1])(1≤l≤r≤n)
固定 l l l不动,那么我们只需要求 s [ r ] s[r] s[r]最大值——也就是静态区间最大
很明显的RMQ了,那么我们就考虑用ST表维护
但是问题是,我们如果用ST去单纯地处理最大值,那么我们只能处理 k = 1 k=1 k=1的情况——我们可以求出 s u m sum sum最大的那一个区间——但是我们需要前 k k k大
是不是有点儿静态区间前 k k k大那味儿了?
于是会有人想要优雅地来写一发主席树
由于博主此时还没有复习到主席树,这里先讲一下堆的做法,以后再把主席树做法补上……
设一个元素为 e l e ( l , r , p o s , b e g ) ele(l,r,pos,beg) ele(l,r,pos,beg), b e g beg beg是枚举的左端点, l l l和 r r r是对应的枚举的右端点, p o s pos pos是取到最大值对应的右端点,这个 p o s pos pos我们用ST表维护
把 b e g = 1 n beg=1~n beg=1 n的元素全部放入堆中,取出区间和最大的那个元素 e l e 0 ( l , r , p o s , b e g ) ele0(l,r,pos,beg) ele0(l,r,pos,beg),加入答案后把 e l e 0 ele0 ele0“拆”成 e l e 1 ( l , p o s − 1 , p o s 1 , b e g ) ele1(l,pos-1,pos1,beg) ele1(l,pos−1,pos1,beg)和 e l e 2 ( p o s + 1 , r , p o s 2 , b e g ) ele2(pos+1,r,pos2,beg) ele2(pos+1,r,pos2,beg)两个元素,其中 p o s 1 pos1 pos1和 p o s 2 pos2 pos2用ST表维护
如法炮制,我们能把前 k k k大的元素全部取出
由于每次加 2 2 2个元素只加了 k − 1 k-1 k−1次,复杂度可以认为是 O ( k l o g N ) O(klogN) O(klogN)
#include<bits/stdc++.h>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int register data=0,w=1;static char ch=0;ch=nc();
while(!isdigit(ch)&&ch!='-')ch=nc();
if(ch=='-')w=-1,ch=nc();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=nc();
return data*w;
}
const int N=5e5+1;
int n,k,L,R,p[N][20],lg[N],s[N];
long long ans;
inline int query(int a,int b){
int register len=lg[b-a+1],x=p[a][len],y=p[b-(1<<len)+1][len];
return s[x]>s[y]?x:y;
}
struct ele{
int l,r,pos,beg;
ele(){}
ele(int l,int r,int beg):l(l),r(r),pos(query(l,r)),beg(beg){}
inline friend bool operator<(const ele&a,const ele&b){return s[a.pos]-s[a.beg-1]<s[b.pos]-s[b.beg-1];}
};
priority_queue<ele>q;
signed main(){
n=rd(),k=rd(),L=rd(),R=rd();
for(int register i=1;i<=n;++i)s[i]=s[i-1]+rd(),p[i][0]=i;
for(int register i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
for(int register j=1;j<=lg[n];++j)
for(int register a,b,i=1;i+(1<<j)-1<=n;++i)
a=p[i][j-1],b=p[i+(1<<j-1)][j-1],p[i][j]=s[a]>s[b]?a:b;
for(int register i=1;i+L-1<=n;++i)q.push(ele(i+L-1,min(n,i+R-1),i));
while(k--){
ele register x=q.top();q.pop();
int register l=x.l,r=x.r,pos=x.pos,beg=x.beg;
ans+=s[pos]-s[beg-1];
if(l!=pos)q.push(ele(l,pos-1,beg));
if(pos!=r)q.push(ele(pos+1,r,beg));
}cout<<ans,exit(0);
}