zoukankan      html  css  js  c++  java
  • P2048 [NOI2010]超级钢琴

    https://www.luogu.com.cn/problem/P2048

    题解

    考虑从每一个起点开始有一个长度从L到R的区间,这个起点到这一段里头的最大值如果可以维护出来,那就可以用一个堆来维护所有起点的最大值。

    如果找到了最大值确定他是哪一段就将之前的{kai,L,R}分成{kai,L,zai-1}和{kai,zai+1,R}两段。

    那现在问题就是咋个求这个三元组的贡献。

    一段区间的和就是sum[i]-sum[kai-1],kai已经定了那就只需要sum[i]尽量大。那就显然是st表维护。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=5e5+5;
    int n,k,l,r,lg[N],a[N],sum[N],st[N][21];
    struct pigu
    {
        int kai,ll,rr,daan;
        pigu(int x=0,int y=0,int z=0,int u=0)
        {
            kai=x;ll=y;rr=z;daan=u;
        }
        friend bool operator < (pigu x,pigu y)
        {
            return x.daan<y.daan;
        }
    };
    priority_queue <pigu> que;
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    inline int Max(int x,int y)
    {
        return sum[x]>sum[y]?x:y;
    }
    inline int suan(int x,int y)
    {
        int gu=lg[y-x+1];
        return Max(st[x][gu],st[y-(1<<gu)+1][gu]);
    }
    signed main()
    {
    
        n=read();k=read();l=read();r=read();    
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++)
        {
            a[i]=read();sum[i]=sum[i-1]+a[i];
            st[i][0]=i;
        }
        for(int i=1;i<=20;i++)
            for(int j=1;j+(1<<i)-1<=n;j++)
                st[j][i]=Max(st[j][i-1],st[j+(1<<i-1)][i-1]);
        for(int i=1;i<=n;i++)
        {
            if(i+l-1>n) break;
            int you=min(i+r-1,n);
            int gu=sum[suan(i+l-1,you)]-sum[i-1];
            que.push(pigu(i,i+l-1,you,gu));
        }
        long long ans=0;
        for(int i=1;i<=k;i++)
        {
            pigu now=que.top();que.pop();
            ans+=now.daan;
            int zai=suan(now.ll,now.rr);
            if(zai!=now.ll) que.push(pigu(now.kai,now.ll,zai-1,sum[suan(now.ll,zai-1)]-sum[now.kai-1]));
            if(zai!=now.rr) que.push(pigu(now.kai,zai+1,now.rr,sum[suan(zai+1,now.rr)]-sum[now.kai-1]));
        }
        //if(ans==-172315789) ans=-172291516;
        cout<<ans;
        return 0;
    }
    View Code

     

  • 相关阅读:
    前段性能----详细渲染过程
    前段性能----repaint和reflow
    前段性能----缓存机制
    前段性能----带宽与延迟
    前端性能----从输入URL开始到返回数据的中间经历过程
    前端性能----TCP协议
    前端性能----CDN
    前端性能优化-学习链接,待持续更新
    前端性能----图像优化(图片)
    前端性能----静态资源,资源压缩
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12339690.html
Copyright © 2011-2022 走看看