zoukankan      html  css  js  c++  java
  • bzoj5050: 建造摩天楼

    Description

    属于小Q管辖的n座摩天楼从左往右排成一排,编号依次为1到n,第i座摩天楼的高度为h_i。小Q会进行m次以下两种
    操作之一:
    2 l r,询问h_l+h_{l+1}+...+h_r。
    1 l r,对于第l到r的每座摩天楼i,如果上次操作结束时h_i<h_{i-1},则将第i座摩天楼再往上造一层,即h_i增加1。
    你可以认为h_0=正无穷。
    请写一个程序回答小Q的每个询问。

    Input

    第一行包含两个正整数n,m(1<=n<=100000,1<=m<=min(100000,2n)),分别表示摩天楼的数量以及操作的数量。
    第二行包含n个正整数h_1,h_2,...,h_n(1<=h_i<=n),表示每座楼的高度。
    接下来m行,每行三个正整数op,l,r(1<=op<=2,1<=l<=r<=n),分别表示每个操作。
    因为小Q觉得错乱不齐的建筑更加美观,因此你可以认为数据是完全随机的。

    Output

    对于每个询问输出一行一个整数,即区间内所有摩天楼的高度之和。

    可以发现对随机数据$h_i-h_{i-1}<0$的变化次数是O(n)的,因此可以用线段树维护操作,注意特判区间端点。维护区间内h的和,再记一些信息表示再操作几次$h_i-h_{i-1}<0$会出现变化,当出现变化时暴力修改。时间复杂度O(nlogn)。

    #include<bits/stdc++.h>
    typedef long long i64;
    const int N=1e5+7,inf=1e8;
    char ib[N*50],*ip=ib;
    int _(){
        int x=0;
        while(*ip<48)++ip;
        while(*ip>47)x=x*10+*ip++-48;
        return x;
    }
    int n,m,h[N],d[N],_l,_r;
    i64 _s;
    inline int min(int a,int b){return a<b?a:b;}
    inline int max(int a,int b){return a>b?a:b;}
    struct node;
    node*at(int x);
    struct node{
        node*lc,*rc;
        int L,R,M,a,sz,v1,v2,v3,cd,dd;
        i64 s;
        void add(int x){
            a+=x;
            s+=sz*i64(x);
            v1+=x,v2-=x;
            if(!M)v3+=dd*x;
        }
        void dn(){
            if(a)lc->add(a),rc->add(a),a=0;
        }
        void set(int x,int y){
            sz=d[L];
            v1=(x<0&&y==1)?x:-inf;
            v2=(x>=0&&y==-1)?x:inf;
            v3=x;
            dd=y;
        }
        void init(){
            s=h[L];
            set(h[L]-h[L-1],d[L]-d[L-1]);
        }
        void up(){
            s=lc->s+rc->s;
            sz=lc->sz+rc->sz;
            v1=max(lc->v1,rc->v1);
            v2=min(lc->v2,rc->v2);
            cd=lc->cd||rc->cd;
        }
        void addl(){
            if(M)dn(),(_l<=M?lc:rc)->addl(),up();
            else{
                cd=(!++v3);
                ++s,++v1,++v2;
            }
        }
        void addr(){
            if(M)dn(),(_r<=M?lc:rc)->addr(),up();
            else{
                cd=(!v3--);
                --v1,--v2;
            }
        }
        void add(){
            if(_l<=L&&R<=_r)return add(1);
            dn();
            if(_l<=M)lc->add();
            if(_r>M)rc->add();
            up();
        }
        void sum(){
            if(_l<=L&&R<=_r)return void(_s+=s);
            dn();
            if(_l<=M)lc->sum();
            if(_r>M)rc->sum();
        }
        bool ir(){
            return v1>=0||v2<0||cd;
        }
        void chk2(){
            if(M)dn(),(_l<=M?lc:rc)->chk2(),up();
            else{
                if(ir()){
                    _l=L+1;
                    d[L]^=1;
                    cd=0;
                }else _l=n+1;
                set(v3,d[L]-d[L-1]);
            }
        }
        void chk(){
            if(M)dn(),(lc->ir()?lc:rc)->chk(),up();
            else{
                _l=L+1;
                d[L]^=1;
                cd=0;
                set(v3,d[L]-d[L-1]);
            }
        }
    }ns[N*2],*np=ns,*rt;
    node*at(int x){
        node*w=rt;
        while(w->M){
            w->dn();
            w=x<=w->M?w->lc:w->rc;
        }
        return w;
    }
    node*build(int L,int R){
        node*w=np++;
        w->L=L,w->R=R;
        if(L<R){
            int M=w->M=(L+R)>>1;
            w->lc=build(L,M);
            w->rc=build(M+1,R);
            w->up();
        }else w->init();
        return w;
    }
    int main(){
        fread(ib,1,sizeof(ib),stdin);
        n=_(),m=_();
        h[0]=inf;
        for(int i=1;i<=n;++i)h[i]=_(),d[i]=h[i]<h[i-1];
        rt=build(1,n);
        for(int o;m;--m){
            o=_(),_l=_(),_r=_();
            if(o==1){
                if(d[_l])rt->addl();
                if(_r<n&&d[_r])++_r,rt->addr(),--_r;
                if(++_l<=_r)rt->add();
                while(rt->ir())for(rt->chk();_l<=n;rt->chk2());
                
            }else{
                _s=0;
                rt->sum();
                printf("%lld
    ",_s);
            }
        }
        return 0;
    }
  • 相关阅读:
    Delphi XE2 之 FireMonkey 入门(16) 滤镜: 实例测试
    Delphi XE2 之 FireMonkey 入门(20) TStyleBook(皮肤、样式相关)
    Delphi XE2 之 FireMonkey 入门(18) TLang(多语言切换的实现)
    Delphi XE2 之 FireMonkey 入门(15) 滤镜: 获取滤镜信息
    ASP.NET中常用功能代码总结(7)——利用Jmail发送和接收邮件
    使用.NET Remoting开发分布式应用——基于租约的生存期
    一个SOA时代的到来,看CSDN新闻有感
    .NET设计模式(3):抽象工厂模式(Abstract Factory)
    ASP.NET中常用功能代码总结(3)——上传图片到数据库
    人的一生 有三件事情不能等
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7690381.html
Copyright © 2011-2022 走看看