测试地址:超级钢琴
做法:题目要求的是,给定数列中长度在
实际上我们可以一个一个地提取出前
取出了最大子段和后,要求次大子段和了,这回要怎么办呢?其实我们可以在求最大子段和的时候排除掉已经取掉的子段,假设这个子段以
注意在使用主席树的时候,要开够空间,不然会RE或WA(只是显示,实质上还是RE)。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define ll long long
using namespace std;
int n,K,L,R,tot=0,a[500010],pos[500010],rt[500010],t[500010];
ll sum[500010];
int seg[20000010],lft[20000010],rht[20000010];
struct forsort {int val,id;} f[500010];
struct state
{
ll val;
int id;
bool operator < (state a) const
{
return val<a.val;
}
};
priority_queue <state> Q;
bool cmp(forsort a,forsort b)
{
return a.val<b.val;
}
void buildtree(int &no,int l,int r)
{
no=++tot;
seg[no]=0;
if (l==r) return;
int mid=(l+r)>>1;
buildtree(lft[no],l,mid);
buildtree(rht[no],mid+1,r);
}
void add(int &no,int last,int l,int r,int x)
{
no=++tot;
seg[no]=seg[last],lft[no]=lft[last],rht[no]=rht[last];
if (l==r)
{
seg[no]++;
return;
}
int mid=(l+r)>>1;
if (x<=mid) add(lft[no],lft[last],l,mid,x);
else add(rht[no],rht[last],mid+1,r,x);
seg[no]=seg[lft[no]]+seg[rht[no]];
}
int query(int l,int r,int k)
{
if (k>seg[rt[r]]-seg[rt[l-1]]) return -1;
int last=rt[l-1],no=rt[r],x=1,y=n+1;
while(x!=y)
{
int mid=(x+y)>>1;
if (seg[lft[no]]-seg[lft[last]]>=k) y=mid,no=lft[no],last=lft[last];
else x=mid+1,k-=seg[lft[no]]-seg[lft[last]],no=rht[no],last=rht[last];
}
return f[x].id-1;
}
void work1()
{
scanf("%d%d%d%d",&n,&K,&L,&R);
f[1].id=1,f[1].val=0;
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i+1].id=i+1,f[i+1].val=f[i].val+a[i];
sum[i]=(ll)f[i+1].val;
}
sort(f+1,f+n+2,cmp);
for(int i=1;i<=n+1;i++)
{
pos[f[i].id]=i;
}
buildtree(rt[0],1,n+1);
for(int i=1;i<=n+1;i++) add(rt[i],rt[i-1],1,n+1,pos[i]);
}
void work2()
{
state next;
for(int i=L;i<=n;i++)
{
t[i]=1;
int p=query(max(i-R+1,1),i-L+1,t[i]);
next.val=sum[i]-sum[p],next.id=i;
Q.push(next);
}
ll ans=0;
while(K--)
{
state now=Q.top();Q.pop();
ans+=now.val;
t[now.id]++;
int p=query(max(now.id-R+1,1),now.id-L+1,t[now.id]);
if (p!=-1)
{
next.val=sum[now.id]-sum[p],next.id=now.id;
Q.push(next);
}
}
printf("%lld",ans);
}
int main()
{
work1();
work2();
return 0;
}