zoukankan      html  css  js  c++  java
  • Miserable Faith

    给定一棵树,每次可以将一条链到根染成一种新的颜色,对于一条边,它的权值在相邻两个点颜色不同时为1,否则为0。

    查询一条路径的边权和,子树里所有点到当前点的距离和,所有路径边权和为0的点对。

    链上染色这个操作,很容易就可以想到用(LCT)来维护,这个就是(LCT)(access)​操作,在进行轻重边转换的时候,相当于我们需要做一个子树加减的操作,这个东西可以用(dfs)序类维护。

    注意在(LCT)加子树的时候要先(findroot)找到真正的根,再去加。

    #include<bits/stdc++.h>
    #define N 100009
    using namespace std;
    typedef long long ll;
    int tot,head[N];
    int n,q;
    ll tr[N<<2],la[N<<2],size[N];
    int dfn[N],p[N][21],deep[N];
    inline ll rd(){
        ll x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{
        int n,to;
    }e[N<<1];
    inline void add(int u,int v){
        e[++tot].n=head[u];
        e[tot].to=v;
        head[u]=tot;
    }
    inline void pushdown(int cnt,int l,int r){
        int mid=(l+r)>>1;
        tr[cnt<<1]+=(mid-l+1)*la[cnt];
        tr[cnt<<1|1]+=(r-mid)*la[cnt];
        la[cnt<<1]+=la[cnt];
        la[cnt<<1|1]+=la[cnt];
        la[cnt]=0; 
    }
    void upd(int cnt,int l,int r,int L,int R,int x){
        if(l>=L&&r<=R){
            tr[cnt]+=x*(r-l+1);
            la[cnt]+=x;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(cnt,l,r);
        if(mid>=L)upd(cnt<<1,l,mid,L,R,x);
        if(mid<R)upd(cnt<<1|1,mid+1,r,L,R,x);
        tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
    }
    ll query(int cnt,int l,int r,int L,int R){
        if(l>=L&&r<=R)return tr[cnt];
        pushdown(cnt,l,r);
        int mid=(l+r)>>1;ll ans=0;
        if(mid>=L)ans+=query(cnt<<1,l,mid,L,R);
        if(mid<R)ans+=query(cnt<<1|1,mid+1,r,L,R);
        return ans; 
    }
    void clear(int cnt,int l,int r){
        tr[cnt]=la[cnt]=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        clear(cnt<<1,l,mid);
        clear(cnt<<1|1,mid+1,r);
    }
    struct LCT{
        #define ls c[x][0]
        #define rs c[x][1]
        int top,c[N][2],fa[N],val[N],rev[N],q[N];
        ll dp[N];
        void clear(){
            for(int i=1;i<=n;++i){
                dp[i]=val[i]=rev[i]=fa[i]=c[i][0]=c[i][1]=0;
            }
        }
        inline void pushup(int x){
            dp[x]=dp[c[x][0]]+dp[c[x][1]]+1;
        }
        inline void pushdown(int x){
            if(rev[x]){
                  rev[ls]^=1;rev[rs]^=1;rev[x]^=1;
                  swap(ls,rs);
            }
        }
        inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
        inline bool ge(int x){return c[fa[x]][1]==x;}
        inline void rotate(int x){
            int y=fa[x],z=fa[y],o=ge(x);
            if(!isroot(y))c[z][ge(y)]=x;
            fa[x]=z;fa[y]=x;fa[c[x][o^1]]=y;
            c[y][o]=c[x][o^1];c[x][o^1]=y;
            pushup(y);pushup(x);
        }
        inline void splay(int x){
            top=1;q[top]=x;
            for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
            for(int i=top;i;--i)pushdown(q[i]);
            while(!isroot(x)){
                int y=fa[x],z=fa[y];
                if(!isroot(y))
                    if(ge(x)==ge(y))rotate(y);
                    else rotate(x);
                rotate(x);
            }
        }
        inline void access(int x){
            for(int y=0;x;y=x,x=fa[x]){
                splay(x);
                int now=c[x][1];
                if(now){  
                   now=find(now);
                   upd(1,1,n,dfn[now],dfn[now]+size[now]-1,1);
                } 
                c[x][1]=y;pushup(x);
                if(y){
                   y=find(y);
                   upd(1,1,n,dfn[y],dfn[y]+size[y]-1,-1);
                }
                
            }
        } 
        inline void makeroot(int x){
            access(x);splay(x);rev[x]^=1;
        }
        inline int find(int x){
            while(c[x][0])pushdown(x),x=c[x][0];
            return x;
        }
        inline void split(int x,int y){
            makeroot(x);access(y);splay(y);
        }
        inline void link(int x,int y){
            makeroot(x);fa[x]=y;
        }
        inline void cut(int x,int y){
            split(x,y);
            if(c[y][0]==x&&fa[x]==y&&!c[x][1])c[y][0]=0,fa[x]=0;
            pushup(y);
        }
    }lc;
    inline int getlca(int u,int v){
        if(deep[u]<deep[v])swap(u,v);
        for(int i=20;i>=0;--i)if(deep[u]-(1<<i)>=deep[v]){
            u=p[u][i];
        }
        if(u==v)return u;
        for(int i=20;i>=0;--i)if(p[u][i]!=p[v][i]){
            u=p[u][i];
            v=p[v][i];
        }
        return p[u][0];
    }
    void dfs(int u,int fa){
        dfn[u]=++dfn[0];
        upd(1,1,n,dfn[u],dfn[u],deep[u]);
        size[u]=1;
        for(int i=1;i<=20;++i)p[u][i]=p[p[u][i-1]][i-1];
        for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
            int v=e[i].to;
            deep[v]=deep[u]+1;p[v][0]=u;
            lc.fa[v]=u;
            dfs(v,u);
            size[u]+=size[v];
        }
    }
    int main(){
        int T;
        scanf("%d",&T); 
        while(T--){
            scanf("%d%d",&n,&q);
            int x,y;
            for(int i=1;i<n;++i){
                scanf("%d%d",&x,&y);
                add(x,y);add(y,x); 
            }
            dfs(1,0);
            int u,v,opt; 
            for(int i=1;i<=q;++i){
                scanf("%d",&opt);
                if(opt==1){
                    scanf("%d%d",&u,&v);
                    lc.split(u,v);
                }
                if(opt==2){
                    scanf("%d%d",&u,&v);
                    int lca=getlca(u,v);
                    int x=query(1,1,n,dfn[u],dfn[u])+query(1,1,n,dfn[v],dfn[v])-2*query(1,1,n,dfn[lca],dfn[lca]);
                    cout<<query(1,1,n,dfn[u],dfn[u])<<" "<<query(1,1,n,dfn[v],dfn[v]);
                    cout<<" "<<query(1,1,n,dfn[lca],dfn[lca])<<" "<<lca<<endl;
    				printf("%d
    ",deep[u]+deep[v]-2*deep[lca]-x);
                }
            }
            for(int i=0;i<=n+1;++i){
                head[i]=deep[i]=size[i]=dfn[i]=0;
            }
            clear(1,1,n);
            lc.clear();
            tot=0; 
        }
        return 0;
    }
    
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/15115979.html
Copyright © 2011-2022 走看看