zoukankan      html  css  js  c++  java
  • [SDOI2008] 洞穴勘测

    Portal

    要求维护一个可以支持断开树边的并查集。

    [n <= 10000, m <= 200009 ]


    LCT的最普通的应用。 直接上模板就好了。


    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define pass {if (true){;}}
    typedef long long LL;
    typedef long double LD;
    int read() {
        char ch = getchar();
        int x = 0, flag = 1;
        for (;!isdigit(ch); ch = getchar()) if (ch == '-') flag *= -1;
        for (;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        return x * flag;
    }
    void write(int x) {
        if (x < 0) putchar('-'), x = -x;
        if (x >= 10) write(x / 10);
        putchar(x % 10 + 48);
    }
    
    template <int N> struct LCT {
    	struct node {
    		int fa, ch[2], revTag, size, wide;
    	}t[N];	
    	int _top, stk[N];
    
    #define fa(x) (t[(x)].fa)
    #define lc(x) (t[(x)].ch[0])
    #define rc(x) (t[(x)].ch[1])
    
    	inline bool isroot(int rt) { return lc(fa(rt)) != rt && rc(fa(rt)) != rt; }
    	void pushup(int rt) { 
    		t[rt].size = t[lc(rt)].size + t[rc(rt)].size + 1; 
    	}
    	void setRev(int rt) { t[rt].revTag ^= 1, swap(lc(rt), rc(rt)); }
    	void pushdown(int rt) {
    		if (t[rt].revTag) {
    			setRev(lc(rt)), setRev(rc(rt));
    			t[rt].revTag = 0;
    		}
    	}   
    
    	void rotate(int rt) {
    		int y = fa(rt), z = fa(y), dir = (rc(y) == rt);
    		if (!isroot(y)) t[z].ch[t[z].ch[1] == y] = rt; t[rt].fa = z;
    		t[y].ch[dir] = t[rt].ch[dir ^ 1]; t[t[rt].ch[dir ^ 1]].fa = y;
    		t[rt].ch[dir ^ 1] = y; t[y].fa = rt;
    		pushup(y); pushup(rt);
    	}
    
    	void splay(int rt) {
    		stk[_top = 1] = rt;
    /**/	for (int u = rt; !isroot(u); u = fa(u)) stk[++_top] = fa(u);
    		while (_top) pushdown(stk[_top--]);
    		while (!isroot(rt)) {
    			int y = fa(rt), z = fa(y);
    /**//**/	if (!isroot(y))
    				(t[z].ch[1] == y) ^ (t[y].ch[1] == rt) ? rotate(rt) : rotate(y);
    			rotate(rt);
    		}
    		pushup(rt);
    	}
    
    	void access(int u) { for (int y = 0; u; u = t[y = u].fa) splay(u), t[u].ch[1] = y, pushup(u); }
    	void makeRoot(int u) { access(u); splay(u); setRev(u); }
    	int findRoot(int u) {
    		access(u); splay(u);
    		while (t[u].ch[0]) pushdown(u), u = t[u].ch[0];
    		return u;
    	}
    	void spilt(int u, int v) { makeRoot(u); access(v); /*?*/ splay(v); }
    	void link(int u, int v) { makeRoot(u); if (findRoot(u) != v) t[u].fa = v; }
    	void cut(int u, int v) {
    		spilt(u, v);
    		if (findRoot(v) == u && t[u].fa == v && t[v].ch[0] == u) {
    			t[u].fa = t[v].ch[0] = 0;
    			pushup(v);
    		}
    	}
    #undef fa                   
    #undef lc
    #undef rc
    };
    
    const int Maxn = 10009;
    LCT <Maxn> s;
    int n, m;
    
    void init() {
    	n = read(), m = read();
    }
    
    char Opt[19];
    void solve() {
    	while (m--) {
    		scanf("%s", Opt);
    		int u = read(), v = read();
    		if (Opt[0] == 'C') s.link(u, v);
    		if (Opt[0] == 'D') s.cut(u, v);
    		if (Opt[0] == 'Q') puts(s.findRoot(u) == s.findRoot(v) ? "Yes" : "No");
    	}
    }
    
    int main() {
    	freopen("LG2147.in", "r", stdin);
    	freopen("LG2147.out", "w", stdout);
    
    	init();
    	solve();
    
    #ifdef Qrsikno
    	debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
    	return 0;
    }
    
  • 相关阅读:
    poj2452
    bnuoj16491
    1326: The contest(并查集+分组背包)
    BNUOJ-1065或运算的简单解法
    递推、规律思维题总结
    uva10160(dfs+状态压缩)
    第七章 人工智能,7.1 基于深度强化学习与自适应在线学习的搜索和推荐算法研究(作者:灵培、霹雳、哲予)
    第六章 大数据,6.3 突破传统,4k大屏的沉浸式体验(作者: 彦川、小丛)
    第六章 大数据,6.2 双11背后的大规模数据处理(作者:惠岸 朋春 谦乐)
    第六章 大数据,6.1 双11数据大屏背后的实时计算处理(作者:藏六 黄晓锋 同杰)
  • 原文地址:https://www.cnblogs.com/qrsikno/p/10121023.html
Copyright © 2011-2022 走看看