题意:小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。 小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。
思路:划分树+priority_queue
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 #define MAXN 510001 9 struct node 10 { 11 int val[MAXN]; 12 int num[MAXN]; 13 }tree[22]; 14 struct heap 15 { 16 int num,k,val; 17 }; 18 priority_queue<heap> Q; 19 int n,m,L,R; 20 int a[MAXN],sorted[MAXN],sum[MAXN]; 21 long long ans=0; 22 bool operator < (const heap &A,const heap &B) 23 { 24 return A.val<B.val; 25 } 26 void build(int t,int left,int right) 27 { 28 if(left==right) 29 return ; 30 int mid=(left+right)/2; 31 int i,isame=0,k1=left-1,k2=mid; 32 for(i=left;i<=right;i++) 33 if(tree[t].val[i]<sorted[mid]) 34 isame++; 35 for(i=left;i<=right;i++) 36 { 37 if(tree[t].val[i]<sorted[mid]) 38 tree[t+1].val[++k1]=tree[t].val[i]; 39 else if(tree[t].val[i]>sorted[mid]) 40 tree[t+1].val[++k2]=tree[t].val[i]; 41 else if(isame<mid-left+1) 42 { 43 tree[t+1].val[++k1]=tree[t].val[i]; 44 isame++; 45 } 46 else 47 { 48 tree[t+1].val[++k2]=tree[t].val[i]; 49 isame++; 50 } 51 tree[t].num[i]=k1+1-left+tree[t].num[left-1]; 52 } 53 build(t+1,left,mid); 54 build(t+1,mid+1,right); 55 } 56 int search(int left,int right,int l,int r,int k,int t) 57 { 58 if(left==right) 59 return tree[t].val[left]; 60 int mid=(left+right)/2; 61 int temp=tree[t].num[r]-tree[t].num[l-1]; 62 int x=tree[t].num[l-1]-tree[t].num[left-1]; 63 int y=tree[t].num[r]-tree[t].num[left-1]; 64 if(temp>=k) 65 return search(left,mid,left+x,left+y-1,k,t+1); 66 else 67 return search(mid+1,right,mid+l-left+1-x,mid+r-left+1-y,k-temp,t+1); 68 } 69 void solve() 70 { 71 int i; 72 for(i=L+1;i<=n;i++) 73 { 74 heap temp; 75 76 temp.val=sum[i]-search(1,n,max(i-R,1),max(i-L,1),1,1); 77 temp.num=i; 78 temp.k=1; 79 Q.push(temp); 80 } 81 for(i=1;i<=m;i++) 82 { 83 heap temp=Q.top(); 84 Q.pop(); 85 ans+=temp.val; 86 int x,y,t; 87 t=temp.num; 88 x=max(t-R,1); y=max(t-L,1); 89 if(y-x+1<=temp.k) 90 continue; 91 temp.val=sum[t]-search(1,n,x,y,temp.k+1,1); 92 temp.k++; 93 Q.push(temp); 94 } 95 printf("%lld\n",ans); 96 } 97 int main() 98 { 99 memset(tree,0,sizeof(tree)); 100 sorted[1]=sum[1]=0; 101 scanf("%d%d%d%d",&n,&m,&L,&R); 102 int i; 103 for(i=1;i<=n;i++) 104 { 105 scanf("%d",a+i); 106 sum[i+1]=sum[i]+a[i]; 107 sorted[i+1]=tree[1].val[i+1]=sum[i+1]; 108 } 109 n++; 110 sort(sorted+1,sorted+n+1); 111 build(1,1,n); 112 solve(); 113 return 0; 114 }