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

    Description

    给你一个n个点的森林,要求支持m个操作:
    1.连接两个点 x,y
    2.询问若断掉 x,y这条边,两点所在联通块乘积的大小

    Hint:

    (n,m<=10^5)

    Solution:

    (LCT)维护子树(size)
    对于每一个点维护(b[i])表示(i)点的虚子树大小
    每次(access)动态更新(b[i])
    (sz[])便可以直接(push\_up)

    #include<bits/stdc++.h>
    using namespace std;
    const int mxn=1e5+5;
    int n,m,t[mxn],fa[mxn],st[mxn],sz[mxn],b[mxn],rev[mxn],val[mxn],ch[mxn][2];
    
    namespace lct {
        int isnotrt(int x) {
            return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
        };
        void push_up(int x) {
            t[x]=t[ch[x][0]]^t[ch[x][1]]^val[x];
            sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+b[x]+1;
        };
        void push_down(int x) {
            if(rev[x]) {
                rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
                swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
                swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
                rev[x]=0;
            }
        }
        void rotate(int x) {
            int y=fa[x],z=fa[y],tp=ch[y][1]==x;
            if(isnotrt(y)) ch[z][ch[z][1]==y]=x;/**/ fa[x]=z;
            ch[y][tp]=ch[x][tp^1],fa[ch[x][tp^1]]=y;
            ch[x][tp^1]=y,fa[y]=x;
            push_up(y),push_up(x);
        };
        void splay(int x) {
            int tp=x,s=0; st[++s]=tp;
            while(isnotrt(tp)) st[++s]=tp=fa[tp];
            while(s) push_down(st[s--]);
            while(isnotrt(x)) {
                int y=fa[x],z=fa[y];
                if(isnotrt(y))  
                    (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
                rotate(x);  
            }
        };
        void access(int x) {
            for(int y=0;x;x=fa[y=x])
                splay(x),b[x]+=sz[ch[x][1]],b[x]-=sz[ch[x][1]=y],push_up(x);
        };
        void makert(int x) {
            access(x); splay(x); 
            swap(ch[x][0],ch[x][1]);
            rev[x]^=1;
        };
        int findrt(int x) {
            access(x); splay(x);
            while(ch[x][0]) push_down(x),x=ch[x][0];
            splay(x); return x;
        };
        void split(int x,int y) {
            makert(x); access(y); splay(y);
        };
        void link(int x,int y) {
            split(x,y); 
            fa[x]=y,b[y]+=sz[x],push_up(y); //因为维护的是子树信息,故为了防止对其他节点信息产生影响,合并时两点都必须splay到根
        };
    }
    using namespace lct;
    
    int main()
    {
        scanf("%d%d",&n,&m); int x,y; char opt[10];
        while(m--) {
            scanf("%s %d %d",opt,&x,&y);
            if(opt[0]=='Q') {
                makert(x); access(y); splay(y);
                printf("%lld
    ",1ll*(sz[y]-sz[x])*(sz[x]));
            }
            else if(opt[0]=='A') link(x,y);
        }
        return 0;
    }
    
  • 相关阅读:
    【POJ】【2420】A Star not a Tree?
    【BZOJ】【2818】Gcd
    【BZOJ】【2190】【SDOI2008】仪仗队
    【Vijos】【1164】曹冲养猪
    【BZOJ】【1430】小猴打架
    【BZOJ】【3611】【HEOI2014】大工程
    【转载】完全图的生成树
    【BZOJ】【2286】【SDOI2011】消耗战
    【POJ】【1061】/【BZOJ】【1477】青蛙的约会
    Codeforces VK Cup Finals #424 Div.1 A. Office Keys(DP)
  • 原文地址:https://www.cnblogs.com/list1/p/10381557.html
Copyright © 2011-2022 走看看