Description
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的
音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级
和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的
所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。
我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
大值是多少。
N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲
Solution
看到求区间和就前缀和,记录点i向左最多和最少能拓展到哪个位置,查询区间最小值就能知道以i为结束点的最优解了
把这样一堆东西扔到优先队列里面每次找最大值,找完就把区间[l,r]分裂成[l,pos-1]和[pos+1,r],其中pos是区间[l,r]的最小值
理论上说线段树改st表能跑得更快的说
Code
#include <stdio.h>
#include <string.h>
#include <queue>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int INF=2000000005;
const int N=500005;
int mn[N*4],p[N*4],a[N];
LL sum[N];
struct data {
int i,l,r,pos;
bool operator <(data b) const {
return sum[i]-sum[pos]<sum[b.i]-sum[b.pos];
}
};
std:: priority_queue <data> heap;
void modify(int now,int tl,int tr,int x,int v) {
if (tl==tr) {
mn[now]=v;
p[now]=tl;
return ;
}
int mid=(tl+tr)>>1;
if (x<=mid) modify(now<<1,tl,mid,x,v);
else modify(now<<1|1,mid+1,tr,x,v);
if (mn[now<<1]<mn[now<<1|1]) p[now]=p[now<<1];
else p[now]=p[now<<1|1];
mn[now]=std:: min(mn[now<<1],mn[now<<1|1]);
}
int query(int now,int tl,int tr,int l,int r) {
if (tl==l&&tr==r) return p[now];
int mid=(tl+tr)>>1;
if (r<=mid) return query(now<<1,tl,mid,l,r);
else if (l>mid) return query(now<<1|1,mid+1,tr,l,r);
else {
int qx=query(now<<1,tl,mid,l,mid);
int qy=query(now<<1|1,mid+1,tr,mid+1,r);
if (sum[qx]<sum[qy]) return qx;
return qy;
}
}
void buildTree(int now,int tl,int tr) {
mn[now]=INF;
if (tl==tr) return ;
int mid=(tl+tr)>>1;
buildTree(now<<1,tl,mid);
buildTree(now<<1|1,mid+1,tr);
}
int main(void) {
freopen("data.in","r",stdin);
int n,m,L,R; scanf("%d%d%d%d",&n,&m,&L,&R);
buildTree(1,0,n);
modify(1,0,n,0,0);
rep(i,1,n) {
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
modify(1,0,n,i,sum[i]);
}
rep(i,L,n) {
data d=(data) {i,std:: max(0,i-R),std:: max(0,i-L)};
d.pos=query(1,0,n,d.l,d.r);
heap.push(d);
}
LL ans=0;
while (m--) {
data top=heap.top(); heap.pop();
ans+=sum[top.i]-sum[top.pos];
data d1=top,d2=top;
d1.r=top.pos-1; d2.l=top.pos+1;
if (d1.l<=d1.r) {
d1.pos=query(1,0,n,d1.l,d1.r);
heap.push(d1);
}
if (d2.l<=d2.r) {
d2.pos=query(1,0,n,d2.l,d2.r);
heap.push(d2);
}
}
printf("%lld\n", ans);
return 0;
}