首页 > 代码库 > bzoj2006: [NOI2010]超级钢琴

bzoj2006: [NOI2010]超级钢琴

ST表+优先队列。维护最大值和最大值的末端。。每次取出最大值后将该区间裂解可以保证取得的是前k个最大值。

#include<cstdio>#include<cstring>#include<cctype>#include<algorithm>#include<queue>#include<cmath>using namespace std;#define rep(i,s,t) for(register int i=s;i<=t;i++)#define dwn(i,s,t) for(register int i=s;i>=t;i--)#define clr(x,c) memset(x,c,sizeof(x))#define ll long longint read(){    int x=0,f=1;char c=getchar();    while(!isdigit(c)){        if(c==‘-‘) f=-1;c=getchar();    }    while(isdigit(c)) x=x*10+c-‘0‘,c=getchar();    return x*f;}const int nmax=500005;const int inf=0x7f7f7f7f;struct node{    int orz,mx,cur,l,r;    node(int orz,int mx,int cur,int l,int r):orz(orz),mx(mx),cur(cur),l(l),r(r){};    node(){};    bool operator<(const node&rhs)const{      return mx<rhs.mx;}};priority_queue<node>q;int n,K,L,R,a[nmax];struct zs{    int u,v;};zs f[nmax][20];zs query(int l,int r){    int t=log(r-l+1)/log(2);    if(f[l][t].u>f[r-(1<<t)+1][t].u) return f[l][t];    else return f[r-(1<<t)+1][t];}void init(){    rep(i,1,n) f[i][0].u=a[i],f[i][0].v=i;    rep(i,1,19){        if((1<<i)>n) break;        rep(j,1,n-1){            if(j+(1<<i)-1>n) break;            if(f[j][i-1].u>f[j+(1<<i-1)][i-1].u) f[j][i]=f[j][i-1];            else f[j][i]=f[j+(1<<i-1)][i-1];        }    }}int main(){    n=read(),K=read(),L=read(),R=read();    rep(i,1,n) a[i]=read()+a[i-1];    init();    int l,r;    rep(i,1,n-L+1){        l=i+L-1,r=min(i+R-1,n);zs o=query(l,r);        q.push(node(i,o.u-a[i-1],o.v,l,r));    }    ll ans=0;node o;zs oo;    rep(i,1,K){        o=q.top();q.pop();        ans+=o.mx;        if(o.cur-1>=o.l) {            oo=query(o.l,o.cur-1);            q.push(node(o.orz,oo.u-a[o.orz-1],oo.v,o.l,o.cur-1));        }        if(o.cur+1<=o.r){            oo=query(o.cur+1,o.r);            q.push(node(o.orz,oo.u-a[o.orz-1],oo.v,o.cur+1,o.r));        }    }    printf("%lld\n",ans);    return 0;}

  

2006: [NOI2010]超级钢琴

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

 
[Submit][Status][Discuss]

bzoj2006: [NOI2010]超级钢琴