BZOJ 2006 [NOI2010]超级钢琴
2006: [NOI2010]超级钢琴
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 1822 Solved: 889
[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,表示按编号从小到大每个音符的美妙度。
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
题解:题意是在n个数字中找出k个不相同的长度在l-r之间的连续子序列,使得权值和最大。
好奇妙的题:首先,只要是枚举两端必然O(n^2),那么就采用控制一端法,比如窝萌枚举头,那么窝萌可以计算出尾的范围。把它们放到一个堆里,取k个不就完了?
等等!这是有很大的问题的!比如窝萌取了i~j这个区间后,这个区间本身不能被取了,但是它的子区间还是可以取的!于是窝萌还要维护一下最大值出现的位置,取了就把这个区间断成两截再放回去,就没有啥问题了。维护这个东西窝用的线段树。其实应该是ST表,可是窝常数小窝怕谁?(逃
然后注意好每个区间的左右+1,-1啥的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 #define CH for(int d=0;d<2;d++)if(ch[d]) 10 #define lson x->ch[0],L,M 11 #define rson x->ch[1],M+1,R 12 using namespace std; 13 const int maxn=500000+10,maxnode=1000000+10,inf=-1u>>1; 14 struct node{ 15 node*ch[2];int pos,x;node(){x=-inf;} 16 void update(){ 17 x=-inf;CH{if(ch[d]->x>x)x=ch[d]->x,pos=ch[d]->pos;}return; 18 } 19 }seg[maxnode],*nodecnt=seg,*root;int n,A[maxn]; 20 void build(node*&x=root,int L=1,int R=n){ 21 x=nodecnt++;int M=L+R>>1;if(L==R)x->pos=L,x->x=A[M]; 22 else build(lson),build(rson),x->update();return; 23 } 24 int ql,qr,_pos,_v,k,L,R; 25 long long ans=0; 26 void query(node*x=root,int L=1,int R=n){ 27 if(ql<=L&&R<=qr){ 28 if(_v<x->x)_v=x->x,_pos=x->pos; 29 }else{int M=L+R>>1; 30 if(ql<=M)query(lson);if(qr>M)query(rson); 31 }return; 32 } 33 struct data{int i,L,R,t;}; 34 bool operator<(const data&a,const data&b){return A[a.t]-A[a.i-1]<A[b.t]-A[b.i-1];} 35 priority_queue<data>Q; 36 inline int read(){ 37 int x=0,sig=1;char ch=getchar(); 38 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; 39 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; 40 return sig?x:-x; 41 } 42 inline void write(long long x){ 43 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 44 int len=0;long long buf[15];while(x)buf[len++]=x%10,x/=10; 45 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 46 } 47 void init(){ 48 n=read();k=read();L=read();R=read(); 49 for(int i=1;i<=n;i++)A[i]=read(),A[i]+=A[i-1]; 50 build(); 51 for(int i=1;i<=n&&i+L-1<=n;i++){ 52 int t=min(n,i+R-1);ql=i+L-1;qr=t;_v=-inf;query(); 53 Q.push((data){i,i+L-1,t,_pos}); 54 } 55 for(int i=1;i<=k;i++){ 56 data t=Q.top();Q.pop(); 57 ans+=A[t.t]-A[t.i-1]; 58 if(t.t-1>=t.L){ql=t.L;qr=t.t-1;_v=-inf;query();Q.push((data){t.i,t.L,t.t-1,_pos});} 59 if(t.t+1<=t.R){ql=t.t+1;qr=t.R;_v=-inf;query();Q.push((data){t.i,t.t+1,t.R,_pos});} 60 } 61 write(ans); 62 return; 63 } 64 void work(){ 65 return; 66 } 67 void print(){ 68 return; 69 } 70 int main(){init();work();print();return 0;}