题意
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。
n,k<=500000,L,R<=n,-1000<=a[i]<=1000
分析
考虑维护前缀和。
对于序列每一个i,我们可以扔一个三元组(id,val,rank)进优先队列里面。id等于i,val表示以i结尾且对答案贡献最大的序列和,rank表示这个贡献对于结尾i而言是第几大的。
那么我们可以每次取堆顶元素,然后把(id,val’,rank+1)扔进优先队列里面。val’表示以id结尾且对答案的贡献为第rank+1大的序列和。
如何快速求出val’呢?我们可以用一棵可持久化线段树来维护前缀和,即可资瓷求区间K大。
复杂度O(klogn)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const int N=500005;
int n,m,L,R,val[N],a[N],a1,root[N],sz,num[N];
struct data
{
int rank,val,id;
bool operator < (const data a) const
{
return val<a.val;
}
};
struct tree{int l,r,s;}t[N*20];
priority_queue<data> q;
void ins(int &d,int p,int l,int r,int x)
{
d=++sz;
t[d]=t[p];t[d].s++;
if (l==r) return;
int mid=(l+r)/2;
if (x<=mid) ins(t[d].l,t[p].l,l,mid,x);
else ins(t[d].r,t[p].r,mid+1,r,x);
}
int kth(int d,int p,int l,int r,int k)
{
if (l==r) return l;
int mid=(l+r)/2;
if (t[t[p].l].s-t[t[d].l].s>=k) return kth(t[d].l,t[p].l,l,mid,k);
else return kth(t[d].r,t[p].r,mid+1,r,k-(t[t[p].l].s-t[t[d].l].s));
}
int main()
{
scanf("%d%d%d%d",&n,&m,&L,&R);
for (int i=2;i<=n+1;i++) scanf("%d",&val[i]),val[i]+=val[i-1],a[++a1]=val[i];
a[++a1]=0;n++;
sort(a+1,a+a1+1);
a1=unique(a+1,a+a1+1)-a-1;
for (int i=1;i<=n;i++) num[i]=lower_bound(a+1,a+a1+1,val[i])-a;
for (int i=1;i<=n;i++) ins(root[i],root[i-1],1,a1,num[i]);
for (int i=2;i<=n;i++)
{
if (i-L<1) continue;
int w=a[kth(root[max(1,i-R)-1],root[i-L],1,a1,1)];
data u;u.id=i;u.val=val[i]-w;u.rank=1;
q.push(u);
}
LL ans=0;
while (m--)
{
data u=q.top();q.pop();
ans+=u.val;
int i=u.id;
if (i-L-max(1,i-R)+1==u.rank) continue;
u.rank++;
int w=a[kth(root[max(1,i-R)-1],root[i-L],1,a1,u.rank)];
u.val=val[i]-w;
q.push(u);
}
printf("%lld",ans);
return 0;
}