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

Description

小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的

音乐。 这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。 一个“超级

和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的

所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。

小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。

我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最

大值是多少。

Solution

oimaster:

用三元组(i, l, r)表示右端点为i,左端点在[l, r]之间和最大的区间([l, r]保证是对于i可行右端点区间的一个子区间),我们用堆维护一些这样的三元组。堆中初始的元素为每个i,并且[l, r]为这个i可行左端点的区间。假如某次最大值为(i, l, r),并且j为那个和最大区间的左端点,那么需要往堆中加入两个三元组(i, l, j-1)和(i, j+1, r)。对于一个三元组,计算对应最大和的问题实际就是一个RMQ问题,可以通过Sparse Table在O(NlogN) – O(1)的时间内解决。这个算法的总时间复杂度为O(NlogN + K log(N+K))

——hzwer.com

懒得写了QwQ

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define MAXN 500005
using namespace std;
typedef long long LL;
int n,k,L,R,a[MAXN],d[MAXN][23];
struct Node
{
    int l,r,a,t;
    Node(int l=0,int r=0,int a=0,int t=0):l(l),r(r),a(a),t(t){}
};
struct cmp
{
    bool operator () (Node x,Node y)
    {return a[x.a]-a[x.t]<a[y.a]-a[y.t];}
};
priority_queue<Node,vector<Node>,cmp>q;
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘){
        if(c==‘-‘)f=-1;c=getchar();
    }
    while(c>=‘0‘&&c<=‘9‘){
        x=(x<<1)+(x<<3)+c-‘0‘;c=getchar();
    }
    return x*f;
}
void RMQ_init()
{
    for(int i=0;i<=n;i++)d[i][0]=i;
    for(int i=1;(1<<i)<=n;i++)
    {
        for(int j=0;j+(1<<i)-1<=n;j++)
        d[j][i]=a[d[j][i-1]]<a[d[j+(1<<(i-1))][i-1]]?d[j][i-1]:d[j+(1<<(i-1))][i-1];
    }
}
int RMQ(int l,int r)
{
    int i=0;
    while((1<<(i+1))<=r-l+1)i++;
    return a[d[l][i]]<a[d[r-(1<<i)+1][i]]?d[l][i]:d[r-(1<<i)+1][i];
}
int main()
{
    n=read(),k=read(),L=read(),R=read();
    for(int i=1;i<=n;i++)
    a[i]=a[i-1]+read();
    RMQ_init();
    for(int i=L;i<=n;i++)
    q.push(Node(max(1,i-R+1),i-L+1,i,RMQ(max(0,i-R),i-L)));
    LL ans=0;
    while(k--)
    {
        Node tmp=q.top();
        q.pop();
        int p=tmp.t;
        ans+=a[tmp.a]-a[p];
        p++;
        if(p-1>=tmp.l)
        q.push(Node(tmp.l,p-1,tmp.a,RMQ(tmp.l-1,p-2)));
        if(p+1<=tmp.r)
        q.push(Node(p+1,tmp.r,tmp.a,RMQ(p,tmp.r-1)));
    }
    printf("%lld\n",ans);
    return 0;
}
时间: 2024-08-24 23:23:14

[BZOJ 2006][NOI2010]超级钢琴(ST表+堆)的相关文章

2006: [NOI2010]超级钢琴|ST表|堆

由于K很小,所以就直接取出最大的K个值加起来即可 考虑一个(i,l,r)表示以i开始以[l,r]中的某个位置结束的区间和的最大值,假设这个位置为p,然后把这些东西都存起来一起扔到堆中,每次取出区间和最大的一个元素,然后继续向堆中添加新的元素,直接对(i,l,p?1),(i,p+1,r)这两个组合再分别找出最大的区间和再扔到堆中,然后重复此过程直到找出前K大 (i,l,r)组合的最大区间和为max(sum[l],sum[l+1]...sum[r])?sum[i?1],找(i,l,r)组合的最大区间

[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可正可负. 一个“超级 和弦”由若干个编号连续的音符组成,

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

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

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

Bzoj 2006: [NOI2010]超级钢琴 堆,ST表

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

BZOJ 2006: [NOI2010]超级钢琴( RMQ + 堆 )

取最大的K个, 用堆和RMQ来加速... ----------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; typedef long long ll; typedef pair<int, int> p

BZOJ 2006: [NOI2010]超级钢琴

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

2006: [NOI2010]超级钢琴 - BZOJ

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

[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; } }