• bzoj2388(分块 凸包)


    好像没有什么高级数据结构能够很高效地实现这个东西;

    那就上万能的分块,我们用一些数形结合的思想,把下标看成横坐标,前缀和的值看成纵坐标;

    给区间内每个数都加k相当于相邻两点的斜率都加上k;

    这种东西我们可以考虑用凸包来维护,因为根据凸包的几何意义,显然最值点在凸包上;

    根据凸包的构造方式,相邻两点的斜率都加上k,在凸包中的点集是不变的,这就很好了;

    每次二分出斜率为零的地方就好了;

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const ll inf=1e16;
    const int maxn=100010;
    int bo,tu[400][400],siz[400],pos[maxn];
    //fir是他被包含在某一个区间加中时,对这个块的贡献;arr时不包含;d是这个块被区间加了多少;
    int m,sta[400],top,n,cnt;
    ll h[maxn],fir[400],arr[400],d[400];
    inline double xl(int x,int y){return double(h[y]-h[x])/double(y-x);}
    //good
    void build(int x){//在x这一块中构造凸包
        int be=(x-1)*bo+1,en=min(x*bo,n);
        top=0;sta[++top]=be;
        for(int i=be+1;i<=en;++i){
            while(top>=2&&xl(sta[top-1],sta[top])<xl(sta[top-1],i))top--;
            sta[++top]=i;
        }
        sta[0]=0;sta[top+1]=n+1;
        siz[x]=top;
        for(int i=0;i<=top+1;++i)tu[x][i]=sta[i];
    }
    //
    //good
    void pushdown(int x){
        ll tmp=fir[x];
        int be=(x-1)*bo+1,en=min(x*bo,n);
        for(int i=be;i<=en;++i){
            h[i]+=tmp;tmp+=d[x];h[i]+=arr[x];
        }
        fir[x]=d[x]=arr[x]=0;
    }
    //
    //good
    ll cal(int p){
        if(p==0||p==n+1)return -inf;
        int x=pos[p];
        return h[p]+fir[x]+d[x]*(p-((x-1)*bo+1))+arr[x];
    }
    //
    //good
    ll fin(int x){
        int l=1,r=siz[x];
        ll h1,h2,h3;
        while(l<=r){
            int mid=(l+r)>>1;
            h1=cal(tu[x][mid-1]),h2=cal(tu[x][mid]),h3=cal(tu[x][mid+1]);
            if(h1<h2&&h2<h3)l=mid+1;
            else {
                if(h1>h2&&h2>h3)r=mid-1;
                else{return h2;}
            }
        }
    }
    //
    int main(){
        cin>>n;
        bo=(int)sqrt(n);
        cnt=(n-1)/bo+1;
        h[0]=h[n+1]=-inf;
        for(int i=1;i<=n;++i){
            scanf("%lld",&h[i]);
        }
        for(int i=2;i<=n;++i){
            h[i]+=h[i-1];
        }
        for(int i=1;i<=n;++i){
            pos[i]=(i-1)/bo+1;
        }
        for(int i=1;i<=cnt;++i)build(i);
        cin>>m;
        int op,x,y,l,r;
        ll k,tmp,ans;
        for(int i=1;i<=m;++i){
            scanf("%d%d%d",&op,&x,&y);
            if(!op){
                scanf("%lld",&k);
                l=pos[x];r=pos[y];
                tmp=k*(l*bo+1-x+1);
                for(int i=l+1;i<=r-1;++i){
                    fir[i]+=tmp;d[i]+=k;
                    tmp+=bo*k;
                }
                pushdown(l);
                tmp=k;
                for(int i=x;i<=min(y,min(l*bo,n));++i)
                h[i]+=tmp,tmp+=k;
                build(l);
                pushdown(r);
                if(l!=r){
                    tmp=k*((r-1)*bo-x+2);
                    for(int i=(r-1)*bo+1;i<=y;++i){
                        h[i]+=tmp;tmp+=k;
                    }
                }
                tmp=k*(y-x+1);
                for(int i=y+1;i<=min(r*bo,n);++i)h[i]+=tmp;
                build(r);
                for(int i=r+1;i<=cnt;++i)arr[i]+=tmp;
            }
            else{
                l=pos[x];r=pos[y];ans=-inf;
                for(int i=l+1;i<r;++i)
                   ans=max(ans,fin(i));
                for(int i=x;i<=min(y,min(l*bo,n));++i){
                   ans=max(ans,cal(i));
                }
                if(l!=r){
                    for(int i=(r-1)*bo+1;i<=y;++i){
                        ans=max(ans,cal(i));
                    }
                }
                printf("%lld
    ",ans);
            }
        }
        system("pause");
        return 0;
    }
  • 相关阅读:
    mysql book网盘
    mysql数据库测试库下载
    TEMP
    测试
    吴炳锡
    ACMUG
    mysql select语句执行顺序
    mysql mha高可用架构的安装
    执行计划解读 简朝阳 (Sky Jian) and 那蓝蓝海
    mysql字符串比较
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/7989378.html
Copyright © 2020-2023  润新知