zoukankan      html  css  js  c++  java
  • 【BZOJ】2006: [NOI2010]超级钢琴

    【题意】给定长度为n的整数序列,求长度为[L,R]的前k大区间和的和。n,k<=500000。

    【算法】堆+贪心+RMQ

    【题解】考虑暴力是取所有长度为[L,R]的子串的前k大求和,复杂度O(n^2)。

    发现左端点相同的区间[l,r]中,最大的区间和就是最大的sum[r](sum是前缀和数组)。

    然后将所以左端点放进堆中,每次取出堆顶之后把第二大的r扔进去,重复k次。

    现在的问题是取区间最大的r,第二大的r……区间第k大?用主席树维护即可,复杂度O(n log n)。

    还可以用ST表(RMQ)维护,定义三元组(x,l,r)表示取左端点为x,右端点为[l,r]的区间最大sum[r]。

    假设对于(x,l,r),取出元素y,就在堆中加入两个三元组(x,l,y-1)和(x,y+1,r)。

    复杂度O(n log n)。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=500010;
    int n,k,L,R,d[maxn][22],sum[maxn],p[maxn][20],logs[maxn];
    struct cyc{
        int x,l,r,y;
        bool operator < (const cyc &a) const
        {return sum[y]-sum[x-1]<sum[a.y]-sum[a.x-1];}
    }qp;
    priority_queue<cyc>q;
    void RMQ_init()
    {
        logs[0]=-1;for(int i=1;i<=n;i++)logs[i]=logs[i>>1]+1;
        for(int i=1;i<=n;i++){d[i][0]=sum[i];p[i][0]=i;}
        for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
            p[i][j]=d[i][j-1]>d[i+(1<<(j-1))][j-1]?p[i][j-1]:p[i+(1<<(j-1))][j-1];
        }
    }
    int RMQ(int l,int r)
    {
        int K=logs[r-l+1];
        return d[l][K]>d[r-(1<<K)+1][K]?p[l][K]:p[r-(1<<K)+1][K];
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&k,&L,&R);
        sum[0]=0;
        for(int i=1;i<=n;i++){scanf("%d",&sum[i]);sum[i]+=sum[i-1];}
        RMQ_init();
        for(int i=1;i<=n;i++){
            if(i+L-1<=n)q.push((cyc){i,i+L-1,min(n,i+R-1),RMQ(i+L-1,min(n,i+R-1))});
        }
        long long ans=0;
        for(int i=1;i<=k;i++)
        {
            qp=q.top();q.pop();
            ans+=sum[qp.y]-sum[qp.x-1];
            if(qp.y>qp.l)q.push((cyc){qp.x,qp.l,qp.y-1,RMQ(qp.l,qp.y-1)});
            if(qp.y<qp.r)q.push((cyc){qp.x,qp.y+1,qp.r,RMQ(qp.y+1,qp.r)});
        }
        printf("%lld",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Css时间轴布局_Css时间轴布局案例整理
    Java Efficient data transfer through zero copy
    Interviewing at Amazon — Leadership Principles
    【转】golang 锁使用---里面的读写锁解析
    【转】MySQL GRANT:用户授权
    【转】mysql处理高并发,防止库存超卖
    [转]Character encoding for commit messages
    【转】git tag的用法
    【转】断网后VirtualBox连接不上问题解决
    【转】sql基础left join, inner join, full join , right join 的理解
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7284328.html
Copyright © 2011-2022 走看看