zoukankan      html  css  js  c++  java
  • 【LOJ】#2230. 「BJOI2014」大融合

    题解

    我现在真是太特么老年了

    一写数据结构就颓废,难受

    这题就是用lct维护子树
    ???lct怎么维护子树

    这样想,我们给每个点记录虚边所在的子树大小,只发生在Access和link的时候
    这样的话我们在这两个操作的时候顺带维护一下就好了

    Access的时候加上新的虚儿子,减掉变成实边的那个儿子
    link直接加上虚儿子的大小即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M;
    namespace lct {
        struct node {
    	int lc,rc,fa,sum,siz;
    	bool rev;
        }tr[MAXN];
    #define lc(u) tr[u].lc
    #define rc(u) tr[u].rc
    #define fa(u) tr[u].fa
    #define sum(u) tr[u].sum
    #define siz(u) tr[u].siz
    #define rev(u) tr[u].rev
        void Init() {
    	for(int i = 1 ; i <= N ; ++i) sum(i) = siz(i) = 1;
        }
        void reverse(int u) {
    	swap(lc(u),rc(u));
    	rev(u) ^= 1;
        }
        void pushdown(int u) {
    	if(rev(u)) {
    	    reverse(lc(u));
    	    reverse(rc(u));
    	    rev(u) = 0;
    	}
        }
        void update(int u) {
    	sum(u) = siz(u);
    	sum(u) += sum(lc(u)) + sum(rc(u));
        }
        bool isRoot(int u) {
    	if(!fa(u)) return true;
    	else return rc(fa(u)) != u && lc(fa(u)) != u;
        } 
        bool which(int u) {
    	return u == rc(fa(u));
        }
        void rotate(int u) {
    	int v = fa(u);
    	if(!isRoot(v)) { (v == lc(fa(v)) ? lc(fa(v)) : rc(fa(v))) = u;}
    	fa(u) = fa(v);fa(v) = u;
    	if(u == lc(v)) {
    	    fa(rc(u)) = v;lc(v) = rc(u);rc(u) = v;
    	}
    	else {
    	    fa(lc(u)) = v;rc(v) = lc(u);lc(u) = v;
    	}
    	update(v);
        }
        void Splay(int u) {
    	static int que[MAXN],qr;
    	qr = 0;
    	int x;
    	for(x = u ; !isRoot(x) ; x = fa(x)) que[++qr] = x;
    	que[++qr] = x;
    	for(int i = qr ; i >= 1 ; --i) pushdown(que[i]);
    	while(!isRoot(u)) {
    	    if(!isRoot(fa(u))) {
    		if(which(fa(u)) == which(u)) rotate(fa(u));
    		else rotate(u);
    	    }
    	    rotate(u);
    	}
    	update(u);
        }
        void Access(int u) {
    	int x;
    	for(x = 0 ; u ; x = u , u = fa(u)) {
    	    Splay(u);
    	    siz(u) += sum(rc(u));
    	    siz(u) -= sum(x);
    	    rc(u) = x;
    	    update(u);
    	}
        }
        void Makeroot(int u) {
    	Access(u);Splay(u);
    	reverse(u);
        }
        void Link(int u,int v) {
    	Makeroot(u);Makeroot(v);Splay(v);
    	fa(v) = u;siz(u) += sum(v);Splay(u);
        }
        int64 Query(int u,int v) {
    	Makeroot(u);Access(v);Splay(u);update(v);
    	return 1LL * (sum(u) - sum(v)) * sum(v);
        }
    }
    void Solve() {
        char op[5];
        int x,y;
        read(N);read(M);
        lct::Init();
        for(int i = 1 ; i <= M ; ++i) {
    	scanf("%s",op + 1);read(x);read(y);
    	if(op[1] == 'A') {
    	    lct::Link(x,y);
    	}
    	else {
    	    out(lct::Query(x,y));enter;
    	}
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    java学习——abstract 和 final
    apache配置访问目录的默认页面
    Beyond Compare 4
    idea常用插件
    linux关闭防火墙
    本地项目上传到gitlab
    删除数据库中多余的数据
    git上传本地项目到gitlab
    谷歌浏览器插件
    域名
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10104998.html
Copyright © 2011-2022 走看看