zoukankan      html  css  js  c++  java
  • BZOJ 2388: 旅行规划 [分块 凸包 等差数列]

    传送门

    题意:

    区间加和询问一段区间内整体前缀和的最大值


    刚才还在想做完这道题做一道区间加等差数列结果发现这道就是....

    唯一的不同在于前缀和一段区间加上等差数列后,区间后面也要加上一个常数!!!

    线段树没法搞吧....分块!

    每个块维护整体加标记,首项,公差

    修改的时候:

    左面不完整的块下放标记暴力重构;

    中间的整块打标记;

    右面不完整的块也是下放标记暴力重构,注意这个地方$r$之外的部分也要更新!

    右面完整的块也要打标记!

    怎么查询呢?

    左右不完整的块暴力查询

    中间的整块,可以发现我们每次修改的只有公差会造成影响,类似于斜率,凸包的形状不会改变(斜率的相对大小不会改变),所以维护一个凸包,查询时三分就行了

    其实我现在还不会三分就去黄学长哪里抄了一个奇怪的东西

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,M=350;
    const ll INF=1e18;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,Q,op,x,y; ll a[N];
    struct _blo{int l,r;}b[M];
    int block,m,pos[N];
    inline void ini(){
        block=sqrt(n); m=(n-1)/block+1;
        for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1 , b[i].r=i*block;
        b[m].r=n;
    }
    
    struct ConvexHull{
        int a[M],n;
        int& operator [](int x){return a[x];}
    }con[M];
    int st[N];
    
    struct Block{
        inline double slope(int i,int j){return (double)(a[i]-a[j])/(i-j);}
        void Set(int x){
            int top=0;
            for(int i=b[x].l ; i<=b[x].r ; i++){
                while(top>1 && slope(i,st[top-1])>=slope(st[top],st[top-1]) ) top--;
                st[++top]=i;
            }
            for(int i=1;i<=top;i++) con[x][i]=st[i]; 
            con[x].n=top; con[x][0]=con[x][top+1]=0;
        }
    
        ll f[M],d[M],add[M];
        void pushDown(int x){
            ll now=f[x];
            for(int i=b[x].l ; i<=b[x].r ; i++) a[i]+=now+add[x],now+=d[x];
            f[x]=d[x]=add[x]=0;
        }
    
        void Add(int l,int r,ll v){
            int pl=pos[l],pr=pos[r];
            ll now=0;
            if(pl==pr){
                pushDown(pl); 
                for(int i=l;i<=r;i++) now+=v,a[i]+=now;
                for(int i=r+1 ; i<=b[pr].r ; i++) a[i]+=now;
                Set(pl);
    
                for(int i=pr+1;i<=m;i++) add[i]+=now;
            }else{
                pushDown(pl);
                for(int i=l ; i<=b[pl].r ; i++) now+=v,a[i]+=now;
                Set(pl);
    
                for(int i=pl+1;i<pr;i++) now+=v,f[i]+=now,d[i]+=v,now+=v*(block-1);
    
                pushDown(pr); 
                for(int i=b[pr].l ; i<=r ; i++) now+=v,a[i]+=now;
                for(int i=r+1 ; i<=b[pr].r ;i++) a[i]+=now;
                Set(pr);
                    
                for(int i=pr+1;i<=m;i++) add[i]+=now;
            }
        }
    
        inline ll cal(int x){ 
            if(x==0) return -INF;//!!!!!
            int t=pos[x]; 
            return a[x]+add[t] + f[t]+d[t]*(x-b[t].l) ; 
        }
        ll Bin(int x){
            int l=1,r=con[x].n;
            while(l<=r){
                int mid=(l+r)>>1;
                ll a=cal(con[x][mid-1]),b=cal(con[x][mid]),c=cal(con[x][mid+1]);
                if(a<b&&b<c) l=mid+1;
                else if(a>b&&b>c) r=mid-1;
                else return b;
            }
            return 0;
        }
        ll Que(int l,int r){
            int pl=pos[l],pr=pos[r];
            ll re=-INF;
            if(pl==pr)
                for(int i=l;i<=r;i++) re=max(re,cal(i));
            else{
                for(int i=l ; i<=b[pl].r ; i++) re=max(re,cal(i));
                for(int i=b[pr].l ; i<=r ; i++) re=max(re,cal(i));
                for(int i=pl+1;i<pr;i++) re=max(re,Bin(i));
            }
            return re;
        }
    }B;
    
    int main(){
        freopen("in","r",stdin);
        n=read(); ini();
        for(int i=1;i<=n;i++) a[i]=read()+a[i-1];
        for(int i=1;i<=m;i++) B.Set(i);
        Q=read();
        while(Q--){
            op=read();x=read();y=read();
            if(op==0) B.Add(x,y,read());
            else printf("%lld
    ",B.Que(x,y));
        }
    }
  • 相关阅读:
    hdu4639 hehe ——斐波纳契数列,找规律
    codefoces round193a
    codeforces 192e
    abbyy cup a
    年中总结
    codeforces 192a
    codeforces 192b
    codeforces 192 c
    codeforces 192 D
    codeforces magic five --快速幂模
  • 原文地址:https://www.cnblogs.com/candy99/p/6556262.html
Copyright © 2011-2022 走看看