zoukankan      html  css  js  c++  java
  • Loj 2230. 「BJOI2014」大融合 (LCT 维护子树信息)

    链接:https://loj.ac/problem/2230

    思路:

    设立siz数组保存虚点信息,sum表示总信息

    维护子树信息link操作和access操作需要进行一些改动

    可参考博客:https://www.cnblogs.com/GXZlegend/p/7061458.html

    实现代码;

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ls c[x][0]
    #define rs c[x][1]
    const int M = 4e5+10;
    const int inf = 1e9;
    int top;
    int sum[M],c[M][2],val[M],fa[M],rev[M],mn[M],S[M];
    int siz[M];
    inline void up(int x){
        sum[x] = sum[ls] + sum[rs] + siz[x] + 1;
    }
    
    inline void pushrev(int x){
        swap(ls,rs); rev[x] ^= 1;
    }
    
    inline bool isroot(int x){
        return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
    }
    
    inline void rotate(int x){
        int y = fa[x],z = fa[y];
        int k = c[y][1] == x;
        if(!isroot(y)) c[z][c[z][1]==y]=x;
        fa[x] = z;
        c[y][k] = c[x][k^1]; fa[c[x][k^1]] = y;
        c[x][k^1] = y; fa[y] = x;
        up(y); up(x);
    }
    
    inline void pushdown(int x){
        if(rev[x]){
            if(ls) pushrev(ls);
            if(rs) pushrev(rs);
            rev[x] = 0;
        }
    }
    
    inline void splay(int x){
        S[top=1]=x;
        for(int i = x;!isroot(i);i=fa[i]) S[++top] = fa[i];
        while(top) pushdown(S[top--]);
        while(!isroot(x)){
            int y = fa[x],z = fa[y];
            if(!isroot(y))
                (c[y][1]==x)^(c[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    
    inline void access(int x){
        //维护子树
        for(int y = 0;x;y = x,x = fa[x])
            splay(x),siz[x] += sum[rs] - sum[y],c[x][1] = y,up(x);
        //for(int y = 0;x;y = x,x = fa[x])
            //splay(x),c[x][1] = y,up(x);
    }
    
    inline void makeroot(int x){
        access(x); splay(x); pushrev(x);
    }
    
    inline void split(int x,int y){
        makeroot(x); access(y); splay(y);
    }
    
    inline void link(int x,int y){
        //维护子树
        makeroot(x); makeroot(y); fa[x] = y; siz[y]+=sum[x]; up(y);
       // makeroot(x);fa[x] = y;
    }
    
    inline void cut(int x,int y){
        split(x,y); fa[x] = c[y][0] = 0; up(y);
    }
    
    inline int findroot(int x){
        access(x); splay(x);
        while(ls) x = ls;
        return x;
    }
    
    int main()
    {
        int n,q,u,v;
        scanf("%d%d",&n,&q);
        char op[10];
        while(q--){
            scanf("%s",op); scanf("%d%d",&u,&v);
            if(op[0] == 'A') link(u,v);
            else {
                split(u,v);
                printf("%lld
    ",1LL*sum[u]*(sum[v]-sum[u]));
            }
        }
    }
  • 相关阅读:
    Unity Animation扩展方法总结
    Unity 离线建造系统
    Unity 任意区域截屏创建Sprite
    Unity ugui拖动控件(地图模式与物件模式)
    Unity 极简UI框架
    Unity 芯片拼图算法
    Unity Procedural Level Generator 基础总结与功能优化
    MANIFEST.MF是个什么?
    外包程序员怎么办?
    文件上传transferTo一行代码的bug
  • 原文地址:https://www.cnblogs.com/kls123/p/10798026.html
Copyright © 2011-2022 走看看