2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 3591 Solved: 1780
[Submit][Status][Discuss]
Description
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的
音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级
和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的
所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。
我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最
大值是多少。
Input
第一行包含四个正整数n, k, L, R。其中n为音符的个数,k为乐曲所包含的超级和弦个数,L和R分别是超级和弦所
包含音符个数的下限和上限。 接下来n行,每行包含一个整数Ai,表示按编号从小到大每个音符的美妙度。
N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲
Output
只有一个整数,表示乐曲美妙度的最大值。
Sample Input
4 3 2 3
3
2
-6
8
3
2
-6
8
Sample Output
11
【样例说明】
共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。
【样例说明】
共有5种不同的超级和弦:
音符1 ~ 2,美妙度为3 + 2 = 5
音符2 ~ 3,美妙度为2 + (-6) = -4
音符3 ~ 4,美妙度为(-6) + 8 = 2
音符1 ~ 3,美妙度为3 + 2 + (-6) = -1
音符2 ~ 4,美妙度为2 + (-6) + 8 = 4
最优方案为:乐曲由和弦1,和弦3,和弦5组成,美妙度为5 + 2 + 4 = 11。
HINT
Source
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstdio> 7 #include<queue> 8 #define maxn 500055 9 #define ll long long 10 using namespace std; 11 int sum[maxn*30],ls[maxn*30],rs[maxn*30],rt[maxn],cnt; 12 int n,K,L,R; 13 int pre[maxn],h[maxn],num[maxn],size[maxn]; 14 struct data { 15 int w,pos; 16 bool operator <(const data tmp) const{return w<tmp.w;} 17 }; 18 priority_queue<data> q; 19 void insert(int &x,int p,int l,int r,int k) { 20 x=++cnt; 21 sum[x]=sum[p]+1,ls[x]=ls[p],rs[x]=rs[p]; 22 if(l==r) {return;} 23 int mid=l+r>>1; 24 if(k<=mid) insert(ls[x],ls[p],l,mid,k); 25 else insert(rs[x],rs[p],mid+1,r,k); 26 } 27 int find(int x,int p,int l,int r,int k) { 28 // cout<<l<<‘ ‘<<r<<‘ ‘<<sum[ls[p]]<<‘ ‘<<sum[ls[x]]<<endl; 29 if(l==r) return l; 30 int mid=l+r>>1; 31 if(sum[ls[p]]-sum[ls[x]]>=k) return find(ls[x],ls[p],l,mid,k); 32 else return find(rs[x],rs[p],mid+1,r,k-(sum[ls[p]]-sum[ls[x]])); 33 } 34 int main() { 35 scanf("%d%d%d%d",&n,&K,&L,&R); 36 h[n+1]=0; 37 for(int i=1;i<=n;i++) { 38 int tmp;scanf("%d",&tmp); 39 pre[i]=pre[i-1]+tmp; 40 h[i]=pre[i]; 41 } 42 sort(h+1,h+n+2); 43 int nn=1; 44 for(int i=2;i<=n+1;i++) if(h[i]!=h[nn]) h[++nn]=h[i]; 45 int hh=lower_bound(h+1,h+nn+1,0)-h; 46 insert(rt[1],rt[1],1,n,hh); 47 for(int i=1;i<=n;i++) { 48 num[i]=lower_bound(h+1,h+nn+1,pre[i])-h; 49 insert(rt[i+1],rt[i],1,n,num[i]); 50 } 51 for(int i=L;i<=n;i++) { 52 if(i-L<0) continue; 53 int w=find(rt[max(i-R,0)],rt[max(i-L+1,0)],1,n,size[i]+1); 54 q.push((data){pre[i]-h[w],i}); 55 } 56 ll ans=0; 57 for(int i=1;i<=K;i++) { 58 int w=q.top().w,pos=q.top().pos; 59 ans+=(ll)w; 60 size[pos]++; 61 q.pop(); 62 int l=max(pos-R+1,1),r=pos-L+1; 63 if(size[pos]>=r-l+1) continue; 64 w=find(rt[l-1],rt[r],1,n,size[pos]+1); 65 w=pre[pos]-h[w]; 66 q.push((data){w,pos}); 67 } 68 printf("%lld\n",ans); 69 }