• bzoj2631: tree


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define mod 51061
    #define maxn 100005
    #define ll unsigned int
    using namespace std;
    
    int n,q,fa[maxn],son[maxn][2],size[maxn];
    bool rev[maxn];
    ll val[maxn],lazyc[maxn],lazyh[maxn],sum[maxn];
    
    struct date{
        int which(int x){
            return son[fa[x]][1]==x;
        }
        bool isroot(int x){
            return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
        }
        void update(int x){
            size[x]=size[son[x][0]]+size[son[x][1]]+1;
            sum[x]=val[x]%mod;
            if (son[x][0]) sum[x]=(sum[x]+sum[son[x][0]])%mod;
            if (son[x][1]) sum[x]=(sum[x]+sum[son[x][1]])%mod;
        }
        void jia(int x,ll y){
            lazyh[x]=(lazyh[x]+y)%mod;
            val[x]=(val[x]+y)%mod;
            sum[x]=(sum[x]+size[x]*y%mod)%mod;
        }
        void cheng(int x,ll y){
            if (lazyh[x]){
                lazyh[x]=(lazyh[x]*y)%mod;
            }
            lazyc[x]=(lazyc[x]*y)%mod;
            val[x]=(val[x]*y)%mod;
            sum[x]=(sum[x]*y)%mod;
        }
        void pushdown(int x){
            if (rev[x]){
                rev[x]^=1,swap(son[x][0],son[x][1]);
                if (son[x][0]) rev[son[x][0]]^=1;
                if (son[x][1]) rev[son[x][1]]^=1;
            }
            if (lazyc[x]!=1){
                if (son[x][0]) cheng(son[x][0],lazyc[x]);
                if (son[x][1]) cheng(son[x][1],lazyc[x]);
                lazyc[x]=1;
            }
            if (lazyh[x]){
                if (son[x][0]) jia(son[x][0],lazyh[x]);
                if (son[x][1]) jia(son[x][1],lazyh[x]);
                lazyh[x]=0;
            }
        }
        void relax(int x){
            if (!isroot(x)) relax(fa[x]);
            pushdown(x);
        }
        void rotata(int x){
            int y=fa[x],d=which(x),dd=which(y);
            if (!isroot(y)) son[fa[y]][dd]=x; fa[x]=fa[y];
            fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
            fa[y]=x,son[x][d^1]=y;
            update(y);
        }
        void splay(int x){
            relax(x);
            while (!isroot(x)){
                if (isroot(fa[x])) rotata(x);
                else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
                else rotata(x),rotata(x);
            }
            update(x);
        }
        void access(int x){
            for (int p=0;x;x=fa[x]){
                splay(x);
                son[x][1]=p;
                update(x);
                p=x;
            }
        }
        void make_root(int x){
            access(x);
            splay(x);
            rev[x]^=1;
        }
        void link(int x,int y){
            make_root(x),fa[x]=y;
        }
        void cut(int x,int y){
            make_root(x);
            access(y);
            splay(y);
            son[y][0]=fa[x]=0;
            update(y);
        }
        void split(int x,int y){
            make_root(x);
            access(y);
            splay(y);
        }
        void add(int x,int y,ll z){
            split(x,y);
            jia(y,z);
        }
        void multiply(int x,int y,ll z){
            split(x,y);
            cheng(y,z);
        }
        void query(int x,int y){
            split(x,y);
            printf("%u
    ",sum[y]%mod);
        }
    }lct;
    
    int main(){
    //    freopen("tree.in","r",stdin);
    //    freopen("tree.out","w",stdout);
        char st[12];
        int u,v,U,V;
        ll UU,VV;
        memset(size,0,sizeof(size));
        memset(fa,0,sizeof(fa));
        memset(son,0,sizeof(son));
        memset(rev,0,sizeof(rev));
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++){
            val[i]=1,sum[i]=1,lazyc[i]=1,lazyh[i]=0,size[i]=1;
        }
        for (int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            lct.link(u,v);
        }
        while (q--){
            scanf("%s%d%d",st+1,&u,&v);
            if (st[1]=='+') scanf("%u",&UU),lct.add(u,v,UU);
            else if (st[1]=='-') scanf("%d%d",&U,&V),lct.cut(u,v),lct.link(U,V);
            else if (st[1]=='*') scanf("%u",&UU),lct.multiply(u,v,UU);
            else lct.query(u,v);
        }
        return 0;
    }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

    做法:链乘链加:先传乘标记,并且把加标记乘上这个数,再传加标记;

    看个变形就很显然了:(ax+b)*c=a*c*x+b*c,显然加标记也要乘上这个数。

  • 相关阅读:
    做一天业务员的感觉:辛苦!
    我的乒乓生涯之三浑浑噩噩的中学六年
    名菊照片(二)
    今天,同事的裤子破了
    昨晚,再一次兵败滑铁卢
    今天去世纪公园看名菊展,拍了好多照片发上来大家一起欣赏:)
    寻找上海市乒友喜欢打乒乓的朋友都进来看看
    同学给我两张f1照片:)
    又搞到几张f1照片,发上来给大家养眼
    我的乒乓生涯之四乒乓姻缘
  • 原文地址:https://www.cnblogs.com/OYzx/p/5503209.html
Copyright © 2020-2023  润新知