zoukankan      html  css  js  c++  java
  • bzoj4530 [Bjoi2014]大融合

    Description

    小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。
    这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够
    联通的树上路过它的简单路径的数量。
    例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因
    为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。
    现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的
    询问。

    Input

    第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。
    接下来的Q行,每行是如下两种格式之一:
    A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。
    Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。
    1≤N,Q≤100000

    Output

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

    树链剖分预处理所有操作完成后的森林,树状数组维护区间和,按顺序处理询问和修改,用并查集维护连通性和当前每棵树的根

    对询问a,b,若fa[b]=a则ans= b的子树大小*(a,b所在树的大小-b的子树大小)

    复杂度O(qlog2n)

    #include<cstdio>
    inline int read(){
        int x=0,c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    inline char readchr(){
        int c=getchar();
        while(c!='A'&&c!='Q')c=getchar();
        return c;
    }
    const int N=100005;
    int n,q,M;
    int f[N],bit[N];
    int qo[N],q1[N],q2[N];
    int es[N*2],enx[N*2],e0[N],ep=2;
    int dep[N],sz[N],fa[N],son[N],top[N],id[N],idp=1;
    inline void inc(int x,int y){
        while(x<M)bit[x]+=y,x+=x&-x;
    }
    inline int sum(int x){
        int s=0;
        while(x)s+=bit[x],x-=x&-x;
        return s+1;
    }
    inline void addedge(int x,int y){
        es[ep]=y;enx[ep]=e0[x];e0[x]=ep++;
        es[ep]=x;enx[ep]=e0[y];e0[y]=ep++;
    }
    void f1(int w,int pa){
        fa[w]=pa;
        sz[w]=1;
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u==pa)continue;
            dep[u]=dep[w]+1;
            f1(u,w);
            sz[w]+=sz[u];
            if(sz[u]>sz[son[w]])son[w]=u;
        }
    }
    void f2(int w,int tp){
        id[w]=idp++;
        top[w]=tp;
        if(son[w])f2(son[w],tp);
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=fa[w]&&u!=son[w])f2(u,u);
        }
    }
    inline void modify(int x,int y,int v){
        int a=top[x],b=top[y];
        while(a!=b){
            inc(id[x]+1,-v);
            inc(id[a],v);
            x=fa[a];a=top[x];
        }
        inc(id[x]+1,-v);
        inc(id[y],v);
    }
    inline int get(int x){
        int a=x,c;
        while(x!=f[x])x=f[x];
        while(x!=(c=f[a]))f[a]=x,a=c;
        return x;
    }
    int main(){
        n=read();q=read();
        M=n+2;
        for(int i=0;i<q;i++){
            qo[i]=readchr();
            q1[i]=read();q2[i]=read();
            if(qo[i]=='A')addedge(q1[i],q2[i]);
        }
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1;i<=n;i++)if(!id[i]){
            f1(i,0);
            f2(i,i);
        }
        for(int i=0;i<q;i++){
            int o=qo[i],a=q1[i],b=q2[i];
            if(o=='A'){
                int c=get(a),d=get(b);
                if(dep[c]<dep[d]){
                    modify(a,c,sum(id[b]));
                    f[d]=c;
                }else{
                    modify(b,d,sum(id[a]));
                    f[c]=d;
                }
            }else{
                if(dep[a]<dep[b]){
                    int s=sum(id[b]);
                    printf("%lld
    ",s*1ll*(sum(id[get(a)])-s));
                }else{
                    int s=sum(id[a]);
                    printf("%lld
    ",s*1ll*(sum(id[get(b)])-s));
                }
            }
        }
        return 0;
    }

    理论上lct复杂度更小...

  • 相关阅读:
    NGINX基本概念
    IP地址进制转换
    路由
    ip ,网段, 网关
    ipaddress模块
    第53课 被遗弃的多重继承(上)
    const static valitate 区别
    第49课 多态的概念和意义 (虚函数virtual)
    第75课 图的遍历(深度优先遍历DFS)
    第74课 图的遍历(广度优先遍历BFS)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5396596.html
Copyright © 2011-2022 走看看