LCT 模板

const int MaxLct = 2 * 1e5;

#define ls(p) (Tr[p].ch[0])
#define rs(p) (Tr[p].ch[1])
#define fa(p) (Tr[p].fa)
#define rev(p) (Tr[p].rev)
struct Node {
    int rev;
    int ch[2], fa;
};
struct Link_Cut_Tree {
    Node Tr[MaxLct + 5];
    int st[MaxLct + 5];

    bool is_root (int p) { return (fa (p) == 0 || (ls (fa (p)) != p && rs (fa (p)) != p)); }
    void Change_Rev (int p) {
    	if (!p) return;
        rev (p) ^= 1; swap (ls (p), rs (p));
    }
    void Push_Down (int p) {
        if (rev (p)) {
            Change_Rev (ls (p)); Change_Rev (rs (p));
            rev (p) = 0;
        }
    }
    void Push_Up (int p) {
        if (!p) return;
        Push_Down (p);
    }
    void Rotate (int x) {
        int y = fa (x), z = fa (y);
        int d = rs (y) == x;
        if (!is_root (y)) Tr[z].ch[Tr[z].ch[1] == y] = x; Tr[x].fa = z;
        Tr[y].ch[d] = Tr[x].ch[!d]; if (Tr[x].ch[!d]) Tr[Tr[x].ch[!d]].fa = y;
        Tr[x].ch[!d] = y; Tr[y].fa = x;
        Push_Up (y); Push_Up (z);
    }
    void splay (int x) {//旋转到所在splay的根
        int y = x, z, tp = 0;
        st[++tp] = y;
        while (!is_root (y)) y = fa (y), st[++tp] = y;
        while (tp) Push_Down (st[tp--]);
        while (!is_root (x)) {
            y = fa (x), z = fa (y);
            if (!is_root (y)) {
                if ((rs (z) == y) ^ (rs (y) == x)) Rotate (x);
                else Rotate (y);
            }
            Rotate (x);
        }
    }
    void Access (int x) {//把原树上 x 到根的路径变为重边
    	int y = x; x = 0;
        for (; y != 0; x = y, y = fa (y)) {
        	splay (y);
        	rs (y) = x;
        	Push_Up (y);
		}
    }
    int Find_Root (int x) {//返回 x 所在原树的根,并把原树的根旋转到辅助树的根
        Access (x), splay (x);
        while (ls (x)) Push_Down (x), x = ls (x);
        return splay (x), x;
    }
    void Make_Root (int x) {//把 x 变为原树的根,并且旋转到辅助树的根
		Access (x);
		splay (x);
		Change_Rev (x);
	}
    void Link (int x, int y) {//建一条 (x, y)
        Make_Root (x);
        if (Find_Root (y) != x) fa (x) = y; //不在一棵树内
    }
    void Cut (int x, int y) {//把 (x, y) 断掉(没有则操作无效)
        Make_Root (x);
		Access (y), splay (y);
        if (Find_Root (y) == x && fa (y) == x && !ls (y)) 
			fa (y) = rs (x) = 0, Push_Up (x);
    }
    void Get (int x, int y) {//取出 x, y 的链,并且把 y 作为辅助树和原树的根 
		Make_Root (y), Access (x), splay (y), Push_Up (y);
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值