• 【BZOJ】2006: [NOI2010]超级钢琴(前缀和+RMQ+堆)


    题目

    传送门:QWQ

    分析

    又不会做。。。。。。。

    显然很好想到前缀和处理一下。

    然后考虑最大化结果,直接上st表。

    问题来了,然后呢?

    怎么做$ length in [l,r]  $ 呢? 

    是设一个五元组 (i,l,r,val,pos) 。

    i是左端点,l,r是右端点范围,val是 i 到 pos的和, pos是 右端点位置。

     然后对于  l,r   二分,扔进优先队列处理 。取出前 k 大,累加一下就是答案。

    完了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=500005;
    int n,posi[maxn][23];
    int sum[maxn],Log2[maxn];
    struct Node{
        int i,l,r,val,pos;
        bool operator < (const Node& a) const{ return val<a.val;}
    };
    
    inline int Max(int x,int y) {return sum[x]>sum[y]? x:y;}
    void ST(){
        Log2[0]=-1;
        for(int i=1;i<=n;i++)
            if((i&(i-1))==0) Log2[i]=Log2[i-1]+1; else Log2[i]=Log2[i-1];
        for(int i=1;i<=n;i++) posi[i][0]=i;
    
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i+(1<<j)<=n+1;i++){
                posi[i][j]=Max(posi[i][j-1],posi[i+(1<<(j-1))][j-1]);
            }
    }
    inline int RMQ(int l,int r){
        int tmp=Log2[r-l+1];
        return Max(posi[l][tmp],posi[r-(1<<tmp)+1][tmp]);
    }
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    priority_queue<Node> que;
    int main()
    {
        int k,L,R;
        scanf("%d%d%d%d",&n,&k,&L,&R);
        for(int i=1;i<=n;i++){
            sum[i]=sum[i-1]+read();
        }
        ST();
        for(int i=1;i<=n+1-L;i++){
            int pos=RMQ(i+L-1,min(n,i+R-1));
    //        printf("---------- %d %d %d
    ",i+L-1,min(n,i+R-1),pos);
            que.push((Node){i,i+L-1,min(n,i+R-1),sum[pos]-sum[i-1],pos});
        }
        ll ans=0;
        while(k){
            Node x=que.top();que.pop();
    //        printf("##########  %d %d %d
    ",x.i,x.pos,x.val);
            k--; ans+=(ll)x.val;
            Node ls=x,rs=x;
            ls.r=x.pos-1; rs.l=x.pos+1;
            if(ls.r>=ls.l) {
                ls.pos=RMQ(ls.l,ls.r); ls.val=sum[ls.pos]-sum[ls.i-1]; que.push(ls);
            }
            if(rs.r>=rs.l) {
                rs.pos=RMQ(rs.l,rs.r); rs.val=sum[rs.pos]-sum[rs.i-1]; que.push(rs);
            }
        }
    //    puts("-----------debug------------");
    //    for(int i=1;i<=n;i++)    printf("%d ",Log2[i]);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    无缝滚动轮播图
    angular 1.6指令与服务
    angular 1.6路由
    javascript 对象
    JavaScript的运算符
    初识JavaScript!
    git常用命令(二)文字版
    CSS水平垂直居中
    收藏的一些牛逼博客
    html5 学习汇总
  • 原文地址:https://www.cnblogs.com/noblex/p/9147570.html
Copyright © 2020-2023  润新知