zoukankan      html  css  js  c++  java
  • [洛谷P3690]【模板】Link Cut Tree (动态树)

    题目大意:给定$n$个点以及每个点的权值,要你处理接下来的$m$个操作。操作有$4$种。操作从$0到3编号。点从1到n编号。

    1. $0,x,y$:代表询问从$x$到$y$的路径上的点的权值的$xor$和。保证$x$到$y$是联通的。
    2. $1,x,y$:代表连接$x$到$y$,若$x$到$y$已经联通则无需连接。
    3. $2,x,y$:代表删除边$(x,y)$,不保证边$(x,y)$存在。
    4. $3,x,y$:代表将点$x$上的权值变成$y$。

    题解:$LCT$

    卡点:

    C++ Code:

    #include <cstdio>
    #define maxn 300010
    #define lc(rt) son[rt][0]
    #define rc(rt) son[rt][1]
    using namespace std;
    int n, m;
    int V[maxn], s[maxn];
    int son[maxn][2], tg[maxn], fa[maxn];
    inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
    inline void swap(int rt) {swap(lc(rt), rc(rt));}
    inline int get(int rt, int flag = 1) {return son[fa[rt]][flag] == rt;}
    inline bool is_root(int rt) {return !(get(rt, 0) || get(rt));}
    inline void pushdown(int rt) {
    	swap(rt);
    	tg[lc(rt)] ^= 1, tg[rc(rt)] ^= 1, tg[rt] ^= 1;
    }
    inline void update(int rt) {s[rt] = s[lc(rt)] ^ s[rc(rt)] ^ V[rt];}
    inline void rotate(int x) {
    	int y = fa[x], z = fa[y], b = get(x);
    	if (!is_root(y)) son[z][get(y)] = x;
    	fa[son[y][b] = son[x][!b]] = y; son[x][!b] = y;
    	fa[y] = x; fa[x] = z;
    	update(y); update(x);
    }
    int stack[maxn], top;
    inline void splay(int x) {
    	stack[top = 1] = x;
    	for (int y = x; !is_root(y); stack[++top] = y = fa[y]);
    	for (; top; top--) if (tg[stack[top]]) pushdown(stack[top]);
    	for (; !is_root(x); rotate(x)) if (!is_root(fa[x])) 
    		get(x) ^ get(fa[x]) ? rotate(x) : rotate(fa[x]);
    	update(x);
    }
    inline void access(int rt) {for (int t = 0; rt; rc(rt) = t, t = rt, rt = fa[rt]) splay(rt);}
    inline void make_root(int rt) {access(rt), splay(rt), tg[rt] ^= 1;}
    inline void link(int x, int y) {make_root(x); fa[x] = y;}
    inline void cut(int x, int y) {make_root(x); access(y); splay(y); fa[x] = lc(y) = 0;}
    inline bool connect(int x, int y) {
    	make_root(x); access(y); splay(y);
    	return fa[x] == y;
    }
    inline bool uni(int x, int y) {
    	make_root(x); access(y); splay(y);
    	int tmp = x;
    	while (tmp) tmp = fa[tmp];
    	return tmp == y;
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &V[i]);
    		s[i] = V[i];
    	}
    	while (m --> 0) {
    		int op, x, y;
    		scanf("%d%d%d", &op, &x, &y);
    		if (op == 0) {
    			make_root(x); access(y); splay(y);
    			printf("%d
    ", s[y]);
    		}
    		if (op == 1) if (!uni(x, y)) link(x, y);
    		if (op == 2) if (connect(x, y)) cut(x, y);
    		if (op == 3) {
    			access(x); splay(x);
    			V[x] = y;
    			update(x);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    关于数组的算法-编程之美读后感-1
    java学习笔记之线程1
    java学习笔记之IO一()
    java学习笔记之泛型
    java学习笔记之正则表达式
    Thinking in java学习笔记之String的不可变性
    Thinking in java学习笔记之map的应用
    Thinking in java学习笔记之set
    scrapy之中间件
    Linux之Redis-redis哨兵集群详解
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9515748.html
Copyright © 2011-2022 走看看