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

    嘟嘟嘟


    好久没写LCT,真的忘了好多。


    这道题是用lct维护子树大小。
    众所周知,最基础的lct只能维护树链上的信息,而因为虚实边的划分导致不能直接维护子树信息。
    所以对于每一个点,我们多维护一个变量(si),在这道题就表示这个点在原树上所有虚儿子的子树大小之和。
    为了防止弄混,我用(all)表示这个节点在原树上的子树大小,于是有(si[now] = sum all[ison])(ison)表示(now)的虚儿子。然后在( exttt{pushup})的时候,有(all[now] = all[rs] +all[ls] + si[now] + 1)
    只有在( exttt{access})的时候才会改变(si[now]),即把原来的虚儿子的大小减去,再加上新的虚儿子的大小。


    ( exttt{access})后一定要再splay一下,更新信息)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<assert.h>
    using namespace std;
    #define enter puts("")
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; (y = e[i].to) && ~i; i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e5 + 5;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) putchar('-'), x = -x;
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen("ha.in", "r", stdin);
    	freopen("ha.out", "w", stdout);
    #endif
    }
    
    char s[2];
    int n, Q;
    struct Lct
    {
    	int ch[2], fa, rev;
    	int all, si;
    }t[maxn];
    #define LS t[now].ch[0]
    #define RS t[now].ch[1]
    In void change(int now)
    {
    	swap(LS, RS), t[now].rev ^= 1;	
    }
    In void pushdown(int now)
    {
    	if(t[now].rev) 
    	{
    		if(LS) change(LS);
    		if(RS) change(RS);
    		t[now].rev = 0;
    	}
    }
    In void pushup(int now) {t[now].all = t[LS].all + t[RS].all + t[now].si + 1;}
    In bool n_root(int x) {return t[t[x].fa].ch[0] == x || t[t[x].fa].ch[1] == x;}
    In void rotate(int x)
    {
    	int y = t[x].fa, z = t[y].fa, k = t[y].ch[1] == x;
    	if(n_root(y)) t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
    	t[y].ch[k] = t[x].ch[k ^ 1], t[t[x].ch[k ^ 1]].fa = y;
    	t[x].ch[k ^ 1] = y, t[y].fa = x;
    	pushup(y), pushup(x);
    }
    int st[maxn], top = 0;
    In void splay(int x)
    {
    	int y = x; st[top = 1] = y;
    	while(n_root(y)) st[++top] = y = t[y].fa;
    	while(top) pushdown(st[top--]);
    	while(n_root(x))
    	{
    		int y = t[x].fa, z = t[y].fa;
    		if(n_root(y)) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
    		rotate(x);
    	}
    }
    In void access(int x)
    {
    	int y = 0;
    	while(x)
    	{
    		splay(x); t[x].si += t[t[x].ch[1]].all - t[y].all;
    		t[x].ch[1] = y; pushup(x);
    		y = x, x = t[x].fa;
    	}
    }
    In void make_root(int x)
    {
    	access(x), splay(x);
    	change(x); 
    }
    In void Link(int x, int y)
    {
    	make_root(x), access(y), splay(y);
    	t[x].fa = y, t[y].si += t[x].all;
    	pushup(y);
    }
    In ll query(int x, int y)
    {
    	make_root(x), access(y), splay(y);
    	return 1LL * (t[y].all - t[x].all) * t[x].all;
    }
    
    int main()
    {
    //	MYFILE();
    	n = read(), Q = read();
    	for(int i = 1; i <= n; ++i) t[i].all = 1;
    	for(int i = 1; i <= Q; ++i)
    	{
    		scanf("%s", s); int x = read(), y = read();
    		if(s[0] == 'A') Link(x, y);
    		else write(query(x, y)), enter;
    	}
    	return 0;
    }
    
  • 相关阅读:
    POJ 3140 Contestants Division (树dp)
    POJ 3107 Godfather (树重心)
    POJ 1655 Balancing Act (树的重心)
    HDU 3534 Tree (经典树形dp)
    HDU 1561 The more, The Better (树形dp)
    HDU 1011 Starship Troopers (树dp)
    Light oj 1085
    Light oj 1013
    Light oj 1134
    FZU 2224 An exciting GCD problem(GCD种类预处理+树状数组维护)同hdu5869
  • 原文地址:https://www.cnblogs.com/mrclr/p/11138077.html
Copyright © 2011-2022 走看看