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

    题面理解很容易,求树上两颗树节点数之和。

    这里需要lct维护虚子树信息。

    对于每个节点,我们记录认的儿子和不认的儿子大小之和(s),和不认的儿子大小和(sx)。

    在access中,x节点换儿子时,需要对x的sx值加上前任儿子值,在减去现任儿子值。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100500
    #define ll long long
    ll n,m;
    ll ch[N][2],fa[N],s[N],sx[N];
    bool rt[N],res[N];
    void update(ll x)
    {
        s[x] = sx[x]+s[ch[x][0]]+s[ch[x][1]]+1;
    }
    void reser(ll x)
    {
        res[x]^=1;
        swap(ch[x][0],ch[x][1]);
    }
    void pushdown(ll x)
    {
        if(res[x])
        {
            res[x]=0;
            reser(ch[x][0]);
            reser(ch[x][1]);
        }
    }
    void down(ll x)
    {
        if(!rt[x])down(fa[x]);
        pushdown(x);
    }
    void rotate(ll x)
    {
        ll y = fa[x] , k = (ch[y][1]==x);
        if(rt[y])rt[y]=0,rt[x]=1;
        else ch[fa[y]][ch[fa[y]][1]==y] = x;
        fa[x] = fa[y];
        ch[y][k] = ch[x][!k],fa[ch[x][!k]] = y;
        ch[x][!k] = y,fa[y] = x;
        update(y),update(x);
    }
    void splay(ll x)
    {
        down(x);
        while(!rt[x])
        {
            ll y = fa[x], z = fa[y];
            if(!rt[y])
                ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
            rotate(x);
        }
    }
    void access(ll x)
    {
        ll y = 0;
        while(x)
        {
            splay(x);
            sx[x]+=s[ch[x][1]];
            sx[x]-=s[y];
            rt[ch[x][1]] = 1,rt[y] = 0;
            ch[x][1] = y;
            update(x);
            y=x,x=fa[x];
        }
    }
    void mtr(ll x)
    {
        access(x);
        splay(x);
        reser(x);
    }
    void link(ll x,ll y)
    {
        mtr(x);
        access(y);
        splay(y);
        fa[x] = y;
        sx[y]+=s[x];
        update(y);
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(ll i=1;i<=n;i++)rt[i]=1,s[i]=1;
        char cc[2];
        ll u,v;
        for(ll i=1;i<=m;i++)
        {
            scanf("%s%lld%lld",cc,&u,&v);
            if(cc[0]=='Q')
            {
                mtr(u);
                access(v);
                splay(u);
                printf("%lld
    ",(s[u]-s[v])*(s[v]));
            }else link(u,v);
        }
        return 0;
    }
  • 相关阅读:
    Windows打开软件老是弹出无法验证发布者
    SpringMvc接受特殊符号参数被转义
    时代更替中的方正
    你应该知道的c# 反射详解
    C#使用System.Data.SQLite操作SQLite
    C# 动态调用WebService
    C# API: 生成和读取Excel文件
    11个强大的Visual Studio调试小技巧
    .Net 垃圾回收和大对象处理
    Visual Studio原生开发的10个调试技巧(一)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9646876.html
Copyright © 2011-2022 走看看