zoukankan      html  css  js  c++  java
  • 【洛谷P1501】【国家集训队】Tree(LCT)

    传送门

    就和线段树维护区间加、乘标记一样
    板子题

    注意虽然模数很小但仍然会爆intint

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define int unsigned int
    inline int read(){
        char ch=getchar();
        int res=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
        return res*f;
    }
    const int N=100005;
    const int mod=51061;
    inline void inc(int &a,int b){
        a=(a+b>=mod)?a+b-mod:a+b;
    }
    inline void mult(int &a,int b){
        a=(a*b)>=mod?a*b%mod:a*b;
    }
    namespace Lct{
        int q[N],rev[N],siz[N],add[N],mul[N],val[N],sum[N],son[N][2],fa[N];
        #define lc(u) son[u][0]
        #define rc(u) son[u][1]
        inline bool isrt(int u){
            if(!fa[u])return 1;
            return lc(fa[u])!=u&&rc(fa[u])!=u;
        }
        inline bool isrc(int u){
            return rc(fa[u])==u;
        }
        inline void pushup(int u){
            siz[u]=1,sum[u]=val[u];
            if(lc(u))siz[u]+=siz[lc(u)],inc(sum[u],sum[lc(u)]);
            if(rc(u))siz[u]+=siz[rc(u)],inc(sum[u],sum[rc(u)]);
        }
        inline void pushmul(int u,int k){
            mult(mul[u],k),mult(add[u],k),mult(val[u],k),mult(sum[u],k);
        }
        inline void pushadd(int u,int k){
            inc(add[u],k),inc(val[u],k),inc(sum[u],siz[u]*k%mod);
        }
        inline void pushdown(int u){
            if(rev[u]){
                if(lc(u))rev[lc(u)]^=1;
                if(rc(u))rev[rc(u)]^=1;
                swap(lc(u),rc(u)),rev[u]=0;
            }
            if(mul[u]!=1){
                pushmul(lc(u),mul[u]),pushmul(rc(u),mul[u]),mul[u]=1;
            }
            if(add[u]){
                pushadd(lc(u),add[u]),pushadd(rc(u),add[u]),add[u]=0;
            }
        }
        inline void rotate(int v){
            int u=fa[v],z=fa[u];
            int t=rc(u)==v;
            if(!isrt(u))son[z][rc(z)==u]=v;
            fa[v]=z;
            son[u][t]=son[v][t^1],fa[son[v][t^1]]=u;
            son[v][t^1]=u,fa[u]=v;
            pushup(u),pushup(v);
        }
        inline void splay(int u){
            q[q[0]=1]=u;
            for(int v=u;!isrt(v);v=fa[v])q[++q[0]]=fa[v];
            for(int i=q[0];i;i--)pushdown(q[i]);
            while(!isrt(u)){
                if(!isrt(fa[u])){
                    if(isrc(u)==isrc(fa[u]))rotate(fa[u]);
                    else rotate(u);
                }
                rotate(u);
            }
            pushup(u);
        }
        inline void access(int u){
            for(int v=0;u;v=u,u=fa[u]){
                splay(u),rc(u)=v;
                if(v)fa[v]=u;
                pushup(u);
            }
        }
        inline int findrt(int u){
            access(u),splay(u);
            while(pushdown(u),lc(u))u=lc(u);
            splay(u);return u;
        }
        inline void makert(int u){
            access(u),splay(u),rev[u]^=1;
        }
        inline void link(int u,int v){
            makert(u),fa[u]=v;
        }
        inline void cut(int u,int v){
            makert(u),access(v),splay(v);
            lc(v)=fa[u]=0,pushup(v);
        }
        inline void split(int u,int v){
            makert(u),access(v),splay(v);
        }
    }
    using namespace Lct;
    char op[5];
    int n,m;
    signed main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)mul[i]=val[i]=1;
        for(int i=1;i<n;i++){
            int u=read(),v=read();
            link(u,v);
        }
        while(m--){
            scanf("%s",op);
            switch(op[0]){
                case '+':{
                    int u=read(),v=read(),k=read();
                    split(u,v),pushadd(v,k);
                    break;
                }
                case '-':{
                    int u=read(),v=read();
                    cut(u,v),u=read(),v=read();
                    link(u,v);
                    break;
                }
                case '/':{
                    int u=read(),v=read();
                    split(u,v),cout<<sum[v]<<'
    ';
                    break;
                }
                default:{
                    int u=read(),v=read(),k=read();
                    split(u,v),pushmul(v,k);
                    break;
                }
            }
        }
    }
    
  • 相关阅读:
    springboot缓存注解——@CacheEvict
    springboot缓存注解——@CachePut
    springboot缓存注解——@Cacheable
    缓存环境
    JSR107缓存规范
    springboot自定义starter
    Linux 最常用命令整理,建议收藏!
    Spring Boot 2.2.0 正式发布,支持 JDK 13!
    厉害了,阿里史上最重要的三段代码…
    代码写成这样,老夫无可奈何!
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145604.html
Copyright © 2011-2022 走看看