• bzoj4389: ZYB and Trees


    Description

    最初有一棵带点权的树。
    给出下列操作:
    1 x y z  在x为根的树里,y到根路径链加z
    2 x y z  x~y链上点权都修改为z
    3 x y    在x为根的树里,对y子树的点权求和 
    4 x y    x~y链上取点权max
    5 x y    x~y链上求点权和
    6 x y    连接 x~y
    7 x y    断开 x~y 

    保证操作1~5上x和y在同一棵树上。
    保证6和7操作合法(即操作前后都是森林)。

    由于子树信息可减,可以用lct维护

    #include<bits/stdc++.h>
    typedef long long i64;
    const int N=200007;
    char ib[15000007],*ip=ib;
    int _(){
        int x=0;
        while(*ip<48)++ip;
        while(*ip>47)x=x*10+*ip++-48;
        return x;
    }
    void pr(i64 x){printf("%lld
    ",x);}
    i64 max(i64 a,i64 b){return a>b?a:b;}
    #define lc c[0]
    #define rc c[1]
    struct node{
        node*c[2],*f;
        int sz,rv,fil;
        i64 v,a,mx,s1,s2;
        void _rv();
        void _a(i64);
        void _fil(int);
        void dn(){
            if(rv)lc->_rv(),rc->_rv(),rv=0;
            if(fil)lc->_fil(fil),rc->_fil(fil),fil=0;
            if(a)lc->_a(a),rc->_a(a),a=0;
        }
        void up(){
            mx=max(v,max(lc->mx,rc->mx));
            s1=v+lc->s1+rc->s1;
            sz=1+lc->sz+rc->sz;
        }
        int wc(){return this==f->rc;}
        bool nrt(){return this==f->lc||this==f->rc;}
    }ns[N],*stk[N];
    void node::_rv(){if(this!=ns)rv^=1,std::swap(lc,rc);}
    void node::_a(i64 x){if(this!=ns)a+=x,v+=x,mx+=x,s1+=sz*x;}
    void node::_fil(int x){if(this!=ns)a=0,v=mx=x,s1=i64(sz)*x,fil=x;}
    int n,m,es[N*2],enx[N*2],e0[N],ep=2;
    void rot(node*x){
        node*f=x->f,*g=f->f;
        int d=x->wc();
        if(f->nrt())g->c[f->wc()]=x;
        x->f=g;
        i64 t=f->s2;
        f->s2-=x->s2-x->c[d^1]->s2;
        x->s2=t;
        (f->c[d]=x->c[d^1])->f=f;
        (x->c[d^1]=f)->f=x;
        f->up();
    }
    void dns(node*a){
        int stp=0;
        for(;a!=ns;stk[++stp]=a,a=a->f);
        while(stp)stk[stp--]->dn();
    }
    void sp(node*x){
        while(x->nrt()){
            node*f=x->f;
            if(f->nrt())rot(f->wc()==x->wc()?f:x);
            rot(x);
        }
    }
    void push(node*x,node*y){
        y->f=x;
        x->s2+=y->s1+y->s2;
    }
    void acs(node*x){
        node*x0=x;
        dns(x);
        for(node*y=ns;x!=ns;y=x,x=x->f){
            sp(x);
            x->s2+=x->rc->s1-y->s1;
            x->rc=y;
            x->up();
        }
        sp(x0);
        x0->up();
    }
    void mrt(node*x){acs(x),x->_rv();}
    void get(node*x,node*y){mrt(x),acs(y);}
    void f1(int w,int pa){
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=pa){
                f1(u,w);
                push(ns+w,ns+u);
            }
        }
    }
    int main(){
        fread(ib,1,sizeof(ib),stdin);
        n=_();
        ns[0]=(node){ns,ns,ns,0,0,0,0,0,0,0,0};
        for(int i=1;i<=n;++i){
            int x=_();
            ns[i]=(node){ns,ns,ns,1,0,0,x,0,x,x,0};
        }
        for(int i=2,a,b;i<=n;++i){
            a=_(),b=i;
            es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        }
        f1(1,0);
        for(m=_();m;--m){
            int o=_();
            node*x=ns+_(),*y=ns+_();
            get(x,y);
            if(o==1)y->_a(_());
            else if(o==2)y->_fil(_());
            else if(o==3)pr(y->v+y->s2-y->lc->s2);
            else if(o==4)pr(y->mx);
            else if(o==5)pr(y->s1);
            else if(o==6)push(y,x);
            else{
                x->f=y->lc=ns;
                y->s2-=x->s2;
                y->up();
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    基础编程练习题第一波
    TYVJ 1541 八数码
    NOIP 2014 寻找道路
    NOIP2014 解方程
    POJ 3213 矩阵乘法(优化)
    POJ 1523 Tarjan求割点
    POJ 3237 树链剖分+线段树
    SPOJ 375 树链剖分
    NOIP 2012 T2 国王游戏 (贪心+高精)
    POJ 1364 差分约束
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7513422.html
Copyright © 2020-2023  润新知