码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4353: Play with tree

时间:2017-02-20 00:01:28      阅读:355      评论:0      收藏:0      [点我收藏+]

标签:类型   sizeof   main   线段   while   span   输出   output   define   

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\n",ans);
    }
    return 0;
}

 

bzoj4353: Play with tree

标签:类型   sizeof   main   线段   while   span   输出   output   define   

原文地址:http://www.cnblogs.com/ccz181078/p/6417770.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!