zoukankan      html  css  js  c++  java
  • BZOJ4530[Bjoi2014]大融合——LCT维护子树信息

    题目描述

    小强要在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)。
    现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的
    询问。

    输入

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

    输出

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

    样例输入

    8 6
    A 2 3
    A 3 4
    A 3 8
    A 8 7
    A 6 5
    Q 3 8

    样例输出

    6
     
    加边操作保证两个联通块都是树,那么LCT维护就好了嘛!
    因为查询时保证x,y之间有边,那么先将x旋到原树的根reverse(x),再将y到根路径变成重链access(y)并将y旋成splay的根splay(y)。
    这样x就是y的左儿子,查询的就是x子树大小和整棵树大小-x子树大小的乘积。注意这里的子树是指原树中的子树。
    平常我们做的LCT都是维护树上路径信息,其实LCT也能维护子树信息。
    我们将LCT上一个点的子节点分为两种:一种是实子节点,也就是这个点在splay上的左右子节点;另一种是虚子节点,就是指向这个点的节点,也就是原树中这个点的轻儿子。
    LCT维护的路径信息是什么?一个点的权值+实子节点子树中的权值和。
    那么LCT维护的子树信息呢?就是一个点的权值+实子节点子树中的权值和+虚子节点子树中的权值和。
    怎么上传虚节点的信息呢?每个节点维护两个信息,一个是原树中整个子树的节点数,一个是原树中所有虚子节点子树的节点数之和。
    我们考虑在什么地方会改变虚子节点的信息:
    1、在access时一个点的右子节点会变成虚子节点,而上一次splay的节点会变成这个点的右子节点。
    2、在link(x,y)时会将x指向y,这时y的虚子节点会多一个x,因此要更新y的信息。
    知道怎么维护子树信息后就可以LCT过这道题了,注意答案爆int。
    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,m;
    int x,y;
    char ch[3];
    int s[100010][2];
    int f[100010];
    int r[100010];
    int st[100010];
    int size[100010];
    int sum[100010];
    int get(int rt)
    {
        return rt==s[f[rt]][1];
    }
    void pushup(int rt)
    {
        sum[rt]=sum[s[rt][0]]+sum[s[rt][1]]+size[rt]+1;
    }
    void pushdown(int rt)
    {
        if(r[rt])
        {
            r[s[rt][0]]^=1;
            r[s[rt][1]]^=1;
            r[rt]^=1;
            swap(s[rt][0],s[rt][1]);
        }
    }
    int is_root(int rt)
    {
        return rt!=s[f[rt]][0]&&rt!=s[f[rt]][1];
    }
    void rotate(int rt)
    {
        int fa=f[rt];
        int anc=f[fa];
        int k=get(rt);
        if(!is_root(fa))
        {
            s[anc][get(fa)]=rt;
        }
        s[fa][k]=s[rt][k^1];
        f[s[fa][k]]=fa;
        s[rt][k^1]=fa;
        f[fa]=rt;
        f[rt]=anc;
        pushup(fa);
        pushup(rt);
    }
    void splay(int rt)
    {
        int top=0;
        st[++top]=rt;
        for(int i=rt;!is_root(i);i=f[i])
        {
            st[++top]=f[i];
        }
        for(int i=top;i>=1;i--)
        {
            pushdown(st[i]);
        }
        for(int fa;!is_root(rt);rotate(rt))
        {
            if(!is_root(fa=f[rt]))
            {
                rotate(get(fa)==get(rt)?fa:rt);
            }
        }
    }
    void access(int rt)
    {
        for(int x=0;rt;x=rt,rt=f[rt])
        {
            splay(rt);
            size[rt]+=sum[s[rt][1]]-sum[x];
            s[rt][1]=x;
            pushup(rt);
        }
    }
    void reverse(int rt)
    {
        access(rt);
        splay(rt);
        r[rt]^=1;
    }
    void link(int x,int y)
    {
        reverse(x);
        reverse(y);
        f[x]=y;
        size[y]+=sum[x];
        pushup(y);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        while(m--)
        {
            scanf("%s",ch);
            scanf("%d%d",&x,&y);
            if(ch[0]=='A')
            {
                link(x,y);
            }
            else
            {
                reverse(x);
                reverse(y);
                printf("%lld
    ",1ll*(sum[y]-sum[x])*sum[x]);
            }
        }
    }
  • 相关阅读:
    用鼠标键盘来控制你的Android手机——同屏显示简单教程
    Ubuntu13.04 Eclipse下编译安装Hadoop插件及使用小例
    eclipse在Ubuntu 13.04下的安装过程及问题小记
    Ubuntu下安装qq方法及疑难问题解决
    POJ1065 Wooden Sticks(贪心+动态规划——单调递减或递增序列)
    简单的字母全排列问题—递归法和STL法
    ichat在线客服jQuery插件(可能是历史上最灵活的)
    轻量级实用JQuery表单验证插件:validateForm5
    一句话在网页右上角加一个精致下拉框:forkme on github
    FastUI快速界面原型制作工具
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9745044.html
Copyright © 2011-2022 走看看