• bzoj4530&&#3805. 大融合


    题目描述:

    小强要在 $N$ 个孤立的星球上建立起一套通信系统。这套通信系统就是连接 $N$ 个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。

    例如,在上图中,现在一共有五条边。其中,$(3,8)$ 这条边的负载是 $6$,因为有六条简单路径 $2-3-8, 2-3-8-7, 3-8, 3-8-7, 4-3-8, 4-3-8-7$ 路过了 $(3,8)$。

    现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问。

    输入:

    第一行包含两个整数 $N,Q$,表示星球的数量和操作的数量。星球从 $1$ 开始编号。

    接下来的 $Q$ 行,每行是如下两种格式之一:
    ``A x y`` 表示在 $x$ 和 $y$ 之间连一条边。保证之前 $x$ 和 $y$ 是不联通的。
    ``Q x y`` 表示询问 $(x,y)$ 这条边上的负载。保证 $x$ 和 $y$ 之间有一条边。

    输出:

    对每个查询操作,输出被查询的边的负载。

    数据范围:

    对于所有数据,$1 leq N,Q leq 100000$。

    算法标签:LCT

    思路:

    可以考虑LCT维护整棵树的情况,维护子树大小情况。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e5+5;
    int n,q,sz[N],v[N];
    il int read(){
        int x,f=1;char ch;
        _(!)ch=='-'?f=-1:f;x=ch^48;
        _()x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    class LCT{
        int son[N][2],fa[N],rev[N],sta[N];
        il bool isroot(int x){
            return (son[fa[x]][0]!=x&&son[fa[x]][1]!=x);
        }
        il void update(int x){
            sz[x]=sz[son[x][0]]+sz[son[x][1]]+v[x];
        }
        il void pushdown(int x){
            if(!rev[x])return;
            swap(son[x][0],son[x][1]);rev[x]=0;
            rev[son[x][0]]^=1;rev[son[x][1]]^=1;
        }
        il void rotate(int x){
            int y=fa[x],z=fa[y],tp=(son[y][1]==x);
            if(!isroot(y))son[z][son[z][1]==y]=x;
            son[y][tp]=son[x][tp^1];fa[son[y][tp]]=y;
            son[x][tp^1]=y;fa[y]=x;fa[x]=z;
            update(y);
        }
        il void splay(int x){
            for(update(x);!isroot(x);rotate(x)){
                int y=fa[x],z=fa[y];
                if(!isroot(y))rotate(((son[y][1]==x)^(son[z][1]==y))?x:y);
            }
            update(x);
        }
        il void access(int x){
            for(int y=0;x;y=x,x=fa[x]){
                splay(x);v[x]+=sz[son[x][1]]-sz[y];
                son[x][1]=y;update(x);
            }
        }
        il void makeroot(int x){
            access(x);splay(x);rev[x]^=1;
        }
    public:
        il void link(int x,int y){
            makeroot(x);makeroot(y);fa[y]=x;
            sz[x]+=sz[y];v[x]+=sz[y];
        }
        il LL query(int x,int y){
            makeroot(x);access(y);splay(y);
            return 1ll*sz[x]*(sz[y]-sz[x]);
        }
    }T;
    int main()
    {
        n=read();q=read();
        for(int i=1;i<=n;i++)v[i]=sz[i]=1;
        while(q--){
            char ch;scanf(" %c",&ch);
            int x=read(),y=read();
            if(ch=='Q')printf("%lld
    ",T.query(x,y));
            else T.link(x,y);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    CentOS中JAVA_HOME的环境变量设置
    Macserver服务更新经常使用的几个shell命令
    一个技术派创业者的反思
    巴斯卡三角形
    iOS中基于 Socket 的 C/S 结构网络通信(中)
    poj 3267 The Cow Lexicon (动态规划)
    Android入门:短信和拨打电话
    HDUOJ--4888--Redraw Beautiful Drawings【isap】网络流+判环
    Dynamics CRM 2015 New Feature (9): Services Changes
    Class 找出一个整形数组中的元素的最大值
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10434998.html
Copyright © 2020-2023  润新知