题意:链接
方法:主席树+堆
解析:
我们这么去想。
对于每一个能成为右端点的点。
我们要拿前k个 sum[i]−sum[j−1] ,首先先处理出所有能成为右端点的点的最小的上面的那一坨。
然后呢我们拿最大的一坨。
之后这时候对于被拿的那一坨的右端点来说。
它的前面的最小的-sum[j]已经不能取了。
所以要取第2小的-sum[j],
这时候再把这个值扔进堆里。
之后一直这么搞下去,从堆里取k个即可。
这时候涉及到一个区间取第k小的操作。
所以上个主席树就好了。
这个复杂度是多少呢?
O(klogn),不虚可过。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 500010
#define M 20000000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,k,l,r,size,heap_root;
int ch[N][2];
int limit[N];
int fa[N];
int root[N];
int lson[M];
int rson[M];
int siz[M];
int sum[N];
int rnk[N];
int val[N];
int h[N];
int a[N];
int find(int x)
{
while(fa[x])x=fa[x];
return x;
}
int merge(int x,int y)
{
if((!x)||(!y))return x+y;
if(val[x]<val[y])swap(x,y);
ch[x][1]=merge(ch[x][1],y);
fa[ch[x][1]]=x;
if(h[ch[x][1]]>h[ch[x][0]])swap(ch[x][1],ch[x][0]);
h[x]=h[ch[x][1]]+1;
return x;
}
void insert(int l,int r,int x,int &y,int val)
{
y=++size;
siz[y]=siz[x]+1;
if(l==r)return;
lson[y]=lson[x],rson[y]=rson[x];
int mid=(l+r)>>1;
if(val<=mid)insert(l,mid,lson[x],lson[y],val);
else insert(mid+1,r,rson[x],rson[y],val);
}
int query(int l,int r,int x,int y,int kth)
{
if(l==r)return l;
int mid=(l+r)>>1;
int num=siz[lson[y]]-siz[lson[x]];
if(num<kth)return query(mid+1,r,rson[x],rson[y],kth-num);
else return query(l,mid,lson[x],lson[y],kth);
}
int main()
{
h[0]=-1;
scanf("%d%d%d%d",&n,&k,&l,&r);
insert(-INF,INF,0,root[1],0);
for(int i=2;i<=n+1;i++)
{
int x;
scanf("%d",&x);
sum[i]=sum[i-1]+x;
insert(-INF,INF,root[i-1],root[i],sum[i]);
rnk[i]=1;
}
val[l+1]=sum[l+1];
for(int i=l+2;i<=n+1;i++)
{
if(i<=r+1)
{
val[i]=sum[i]-query(-INF,INF,root[1-1],root[i-l],rnk[i]);
limit[i]=i-l+1;
}
else
{
int t=query(-INF,INF,root[i-r-1],root[i-l],rnk[i]);
val[i]=sum[i]-query(-INF,INF,root[i-r-1],root[i-l],rnk[i]);
limit[i]=r-l+1;
}
rnk[i]++;
heap_root=merge(find(i-1),i);
fa[heap_root]=0;
}
ll ans=0;
for(int i=1;i<=k;i++)
{
ans+=val[heap_root];
int flag=0;
if(rnk[heap_root]<=limit[heap_root])
{
if(heap_root<=r)
{
val[heap_root]=sum[heap_root]-query(-INF,INF,root[1-1],root[heap_root-l],rnk[heap_root]);
}
else
{
val[heap_root]=sum[heap_root]-query(-INF,INF,root[heap_root-r-1],root[heap_root-l],rnk[heap_root]);
}
flag=1;
}
rnk[heap_root]++;
int pre=heap_root;
heap_root=merge(ch[heap_root][0],ch[heap_root][1]);
fa[heap_root]=0;
fa[pre]=0,ch[pre][0]=ch[pre][1]=0;
if(flag){heap_root=merge(heap_root,pre);fa[heap_root]=0;}
}
printf("%lld\n",ans);
}