bzoj2006 [NOI2010]超级钢琴

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<=500000,k<=500000,-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。

正解:ST表+堆。然而我写的主席树。

跪求压常数大法,我的代码虽然bzoj上过了,但是只是总时间过了而已。。2s的点要跑3s。。

我们考虑建一棵主席树,第i棵树表示以i为起点的符合条件的和弦。然后我们就可以二分一个权值。当我们二分出权值后,把所有>=权值的数的个数都算出来,并求出这些和弦的和,如果个数>=k,那么就是合法的,如果<k就是不合法的。还有最后计算答案的时候,一定要减去重复的和弦。如果是主席树的话,那么要离散化,把空间压下来。我调了很久都是因为空间问题。。

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (500000000)
15 #define N (500010)
16 #define il inline
17 #define RG register
18 #define ll long long
19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
20 
21 using namespace std;
22 
23 struct node{ ll tot,sum; };
24 
25 int ls[40*N],rs[40*N],rt[N],a[N],v[N],hsh[N],k,l,r,n,nn,TT,sz;
26 ll tt[40*N],ss[40*N],ans;
27 
28 il int gi(){
29     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
30     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
31 }
32 
33 il void insert(RG int x,RG int &y,RG int l,RG int r,RG int k,RG int v,RG int fg){
34     tt[y=++sz]=tt[x]+fg,ss[y]=ss[x]+v*fg,ls[y]=ls[x],rs[y]=rs[x];
35     if (l==r) return; RG int mid=(l+r)>>1;
36     k<=mid ? insert(ls[x],ls[y],l,mid,k,v,fg) : insert(rs[x],rs[y],mid+1,r,k,v,fg); return;
37 }
38 
39 il node query(RG int x,RG int l,RG int r,RG int v){
40     RG int mid; RG ll tot=0,sum=0;
41     while (l<r){
42     mid=(l+r)>>1;
43     if (v<=mid) tot+=tt[rs[x]],sum+=ss[rs[x]],r=mid,x=ls[x];
44     else l=mid+1,x=rs[x];
45     }
46     return (node){tot+tt[x],sum+ss[x]};
47 }
48 
49 il node check(RG int key){
50     RG ll tot=0,sum=0; RG node res;
51     for (RG int i=1;i<=nn;++i){
52     if (key+v[i-1]>hsh[TT]) continue;
53     RG int kk=lower_bound(hsh+1,hsh+TT+1,key+v[i-1])-hsh;
54     res=query(rt[i],1,TT,kk),tot+=res.tot,sum+=res.sum-res.tot*v[i-1];
55     }
56     return (node){tot,sum};
57 }
58 
59 il void work(){
60     n=gi(),k=gi(),l=gi(),r=gi(),nn=n-l+1;
61     for (RG int i=1;i<=n;++i) hsh[++TT]=a[i]=gi()+a[i-1];
62     sort(hsh+1,hsh+TT+1),TT=unique(hsh+1,hsh+TT+1)-hsh-1;
63     for (RG int i=1;i<=n;++i) v[i]=a[i],a[i]=lower_bound(hsh+1,hsh+TT+1,a[i])-hsh;
64     for (RG int i=l;i<=r;++i) insert(rt[1],rt[1],1,TT,a[i],v[i],1);
65     for (RG int i=2;i<=nn;++i){
66     insert(rt[i-1],rt[i],1,TT,a[l+i-2],v[l+i-2],-1);
67     if (r+i-1<=n) insert(rt[i],rt[i],1,TT,a[r+i-1],v[r+i-1],1);
68     }
69     RG int l=-inf,r=inf,mid; RG ll tot,res;
70     while (l<=r){
71     mid=(l+r)>>1; RG node bl=check(mid);
72     if (bl.tot<k) r=mid-1; else tot=bl.tot,ans=bl.sum,res=mid,l=mid+1;
73     }
74     printf("%lld
",ans-(ll)res*(tot-(ll)k)); return;
75 }
76 
77 int main(){
78     File("piano");
79     work();
80     return 0;
81 }
原文地址:https://www.cnblogs.com/wfj2048/p/6508853.html