zoukankan      html  css  js  c++  java
  • bzoj4353: Play with tree

    Description

    给你一棵包含N个节点的树,设每条边一开始的边权为0,现在有两种操作:
     
    1)给出参数U,V,C,表示把U与V之间的路径上的边权变成C(保证C≥0)
     
    2)给出参数U,V,C,表示把U与V之间的路径上的边权加上C。但是如果U至V之间路径某条边的边权加上C小于0,那么C=这条边的边权的相反数。
     
    你需要统计出每次一操作过后树中边权为0的边有多少条。

    Input

    第一行两个整数N,M,分别表示表示节点个数与操作数。
    接下来N-1行每行两个整数X,Y表示X,Y之间有一条边。
    接下来M行每行4个整数P,U,V,C,P表示操作类型,U,V,C的意义见题目描述。

    Output

    输出文件包括M行,每行一个整数,表示边权为0的边的个数。
    树链剖分+线段树维护一下区间最小值和个数、覆盖标记、加法标记
    #include<cstdio>
    #include<algorithm>
    typedef long long i64;
    const int N=100007;
    const i64 fil_0=1ll<<60;
    char buf[6000007],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr,f=1;
        while(c<48)c=='-'&&(f=-1),c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x*f;
    }
    int n,m,es[N*2],enx[N*2],e0[N],ep=2,ans=0;
    int fa[N],sz[N],dep[N],top[N],son[N],id[N],idp=0;
    int _l,_r;
    i64 _a;
    struct node{
        node*lc,*rc;
        i64 mn,fil,a;
        int L,R,mc;
        int c0(){
            return mn?0:mc;
        }
        void _fil(i64 x){
            mn=fil=x;
            mc=R-L+1;
            a=0;
        }
        void _add(i64 x){
            if(fil!=fil_0)fil+=x;
            mn+=x;a+=x;
        }
        void fils(){
            if(_l<=L&&R<=_r){
                _fil(_a);
                return;
            }
            dn();
            int M=L+R>>1;
            if(_l<=M)lc->fils();
            if(_r>M)rc->fils();
            up();
        }
        void mns(){
            if(mn>=_a)return;
            if(_l<=L&&R<=_r){
                _a=mn;
                return;
            }
            dn();
            int M=L+R>>1;
            if(_l<=M)lc->mns();
            if(_r>M)rc->mns();
        }
        void adds(){
            if(_l<=L&&R<=_r){
                _add(_a);
                return;
            }
            dn();
            int M=L+R>>1;
            if(_l<=M)lc->adds();
            if(_r>M)rc->adds();
            up();
        }
        void dn(){
            if(a){
                lc->_add(a);
                rc->_add(a);
                a=0;
            }
            if(fil!=fil_0){
                lc->_fil(fil);
                rc->_fil(fil);
                fil=fil_0;
            }
        }
        void up(){
            mn=lc->mn<rc->mn?lc->mn:rc->mn;
            mc=0;
            if(mn==lc->mn)mc+=lc->mc;
            if(mn==rc->mn)mc+=rc->mc;
        }
    }ns[N*2],*np=ns,*rt[N];
    node*build(int L,int R){
        node*w=np++;
        w->L=L;w->R=R;
        if(L!=R){
            int M=L+R>>1;
            w->lc=build(L,M);
            w->rc=build(M+1,R);
            w->up();
        }else{
            w->mn=0;w->mc=1;
            w->fil=fil_0;
        }
        return w;
    }
    #define F(a,b) ans-=a->c0(),a->b(),ans+=a->c0()
    void fils(int x,int y,i64 c){
        int a=top[x],b=top[y];
        _a=c;
        while(a!=b){
            if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
            _l=id[a],_r=id[x];
            F(rt[a],fils);
            x=fa[a];a=top[x];
        }
        if(dep[x]>dep[y])std::swap(x,y);
        _l=id[x]+1,_r=id[y];
        if(_l<=_r)F(rt[top[x]],fils);
    }
    void mns(int x,int y,i64 c){
        int a=top[x],b=top[y];
        _a=c;
        while(a!=b){
            if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
            _l=id[a],_r=id[x];
            rt[a]->mns();
            x=fa[a];a=top[x];
        }
        if(dep[x]>dep[y])std::swap(x,y);
        _l=id[x]+1,_r=id[y];
        if(_l<=_r)rt[top[x]]->mns();
    }
    void adds(int x,int y,i64 c){
        mns(x,y,-c);
        _a*=-1;
        int a=top[x],b=top[y];
        while(a!=b){
            if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
            _l=id[a],_r=id[x];
            F(rt[a],adds);
            x=fa[a];a=top[x];
        }
        if(dep[x]>dep[y])std::swap(x,y);
        _l=id[x]+1,_r=id[y];
        if(_l<=_r)F(rt[top[x]],adds);
    }
    void f1(int w,int pa){
        dep[w]=dep[fa[w]=pa]+1;
        sz[w]=1;
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=pa){
                f1(u,w);
                sz[w]+=sz[u];
                if(sz[u]>sz[son[w]])son[w]=u;
            }
        }
    }
    void f2(int w,int tp){
        top[w]=tp;
        id[w]=++idp;
        if(son[w])f2(son[w],tp);
        else rt[tp]=build(id[tp],id[w]);
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=fa[w]&&u!=son[w])f2(u,u);
        }
    }
    int main(){
        buf[fread(buf,1,sizeof(buf),stdin)]=0;
        n=_();m=_();
        for(int i=1,a,b;i<n;++i){
            a=_();b=_();
            es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        }
        f1(1,0);f2(1,1);
        ans=n-1;
        for(int i=0,o,u,v,c;i<m;++i){
            o=_();u=_();v=_();c=_();
            if(o==1)fils(u,v,c);
            else adds(u,v,c);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Python单元测试框架之pytest 2 -- 生成测试报告
    Python单元测试框架之pytest 1 ---如何执行测试用例
    pytest学习笔记
    Python selenium —— selenium与自动化测试成神之路
    [LeetCode 41.] 缺失的第一个正数
    [LeetCode 802.] 找到最终的安全状态
    [LeetCoe 1116.] 打印零与奇偶数
    [LeetCode 1115.] 交替打印FooBar
    [LeetCode 146.] LRU 缓存机制
    [LeetCode 300.] 最长递增子序列
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6417770.html
Copyright © 2011-2022 走看看