[BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列

2006: [NOI2010]超级钢琴

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 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

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。

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 }

原文地址:https://www.cnblogs.com/wls001/p/8524939.html

时间: 2024-12-09 13:54:44

[BZOJ2006] [NOI2010]超级钢琴 主席树+贪心+优先队列的相关文章

bzoj2006 noi2010 超级钢琴 主席树 + 优先队列

Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2435  Solved: 1195 Description 小 Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负. 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R.我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和.两

[NOI2010]超级钢琴 划分树+堆

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define N 510000 struct P{ int x,y; P(int a=0,int b=0){x=a,y=b;} bool operator<(P a)const{ return y<a.y; } }

[BZOJ2006][NOI2010]超级钢琴(ST表+堆)

2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3679  Solved: 1828[Submit][Status][Discuss] Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负. 一个“超级 和弦”由若干个编号连续的音符组成,

[NOI2010][bzoj2006] 超级钢琴 [主席树/ST表+堆]

题面: 传送门 思路: 首先容易想到用堆维护的O(n2logn)暴力 那么肯定就是在这个基础上套数据结构了[愉快] 然而我因为过于蒟蒻......只想得到主席树暴力***过去的方法 大概就是把前缀和算出来,然后放到一棵线段树里面 对于每一个i(i=1...(n-L+1)),线段树查询以i为左端点的所有区间右端点中,前缀和最大的一个 因为区间[i,j]可以变成pre[j]-pre[i]的形式,那么只需要最大化pre[j]就可以了 一开始,对于所有的i把这个最大值求出来,减掉pre[i-1],再放到

bzoj2006 [NOI2010]超级钢琴 [优先队列|RMQ]

Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负. 一个"超级和弦"由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R.我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和.两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的. 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得

[luogu2048] [bzoj2006] [NOI2010] 超级钢琴 题解

花了一个星期,总算把这一道该死的毒瘤题做完了. 这道题有很多种解法,我是用优先队列+主席树. 首先每一个区间的和,可以表示为两个前缀和之差. 我们显然可以知道,每一次找到的那个最大值必然在以一个点为最后一个点的区间之内. 所以我们可以把每一个点为最后一个点的最大值的区间求出来,先打入队列. 然后每一次打出来一个值,我们就把这个区间的最后一个值的位置的排名前一名的那一个区间打入队列. 这样重复计算即可. 至于实现,我们可以将每一个前缀和建一个主席树,然后我们维护一个三元组(add,cnt,end)

BZOJ 2006 NOI2010 超级钢琴 划分树+堆

题目大意:给定一个序列,找到k个长度在[l,r]之间的序列,使得和最大 暴力O(n^2logn).肯定过不去 看到这题的第一眼我OTZ了一下午...后来研究了非常久别人的题解才弄明确怎么回事...蒟蒻果然不能理解大神的思路啊0.0 首先维护前缀和,那么以第i个元素结尾的和最大的序列自然就是sum[i]-min{sum[j]}(i-r<=j<=i-l) 然后我们维护一个大根堆.每取走一个以i为结尾的元素,增加sum[i]-2thmin{sum[j]},再取走这个元素就增加sum[i]-3thmi

bzoj2006 [NOI2010]超级钢琴

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2006 [题解] 思路巧妙啊! 前置技能:序列和可以转化成前缀和的形式,那么前缀和左端点固定了右端点就是区间找最大值了. 记录五元组(from, l, r, pos, val)表示从from开始,右端点在[l,r]之间,在pos处取max,取max的值是val. 那么按照val扔到堆里,每次取出最大的,从pos分裂成两半,要兹磁求最大值,所以st表就行了. # include <queue>

【BZOJ2006】[NOI2010]超级钢琴 ST表+堆

[BZOJ2006][NOI2010]超级钢琴 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度为Ai,其中Ai可正可负. 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R.我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和.两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的. 小Z决定创作