• LCT 常用模板


    动态维护链上信息

    例题:P3690 【模板】Link Cut Tree(动态树)

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 100003, M = N << 1;
    
    int n, m;
    int fa[N], c[N][2], v[N], s[N], stk[N];
    bool r[N];
    
    inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
    
    inline void pushup(int x) {s[x] = s[c[x][0]] ^ s[c[x][1]] ^ v[x];}
    
    inline void pushr(int x) {swap(c[x][0], c[x][1]), r[x] ^= 1;}
    
    inline void pushdown(int x)
    {
    	if (r[x])
    	{
    		if (c[x][0]) pushr(c[x][0]);
    		if (c[x][1]) pushr(c[x][1]);
    		r[x] = 0;
    	}
    }
    
    inline void rotate(int x)
    {
    	int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
    	if (isroot(y)) c[z][c[z][1] == y] = x;
    	c[x][!k] = y, c[y][k] = w;
    	if (w) fa[w] = y;
    	fa[x] = z, fa[y] = x;
    	pushup(y);
    }
    
    inline void splay(int x)
    {
    	int y = x, z = 0;
    	stk[z = 1] = y;
    	while (isroot(y)) stk[++z] = y = fa[y];
    	while (z) pushdown(stk[z--]);
    	while (isroot(x))
    	{
    		y = fa[x], z = fa[y];
    		if (isroot(y))
    			rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
    		rotate(x);
    	}
    	pushup(x);
    }
    
    inline void access(int x)
    {
    	for (int y = 0; x; x = fa[y = x])
    		splay(x), c[x][1] = y, pushup(x);
    }
    
    inline void makeroot(int x)
    {
    	access(x); splay(x);
    	pushr(x);
    }
    
    inline int findroot(int x)
    {
    	access(x); splay(x);
    	while (c[x][0]) pushdown(x), x = c[x][0];
    	splay(x);
    	return x;
    }
    
    inline void split(int x, int y)
    {
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    inline void link(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) != x) fa[x] = y;
    }
    
    inline void cut(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) == x && fa[y] == x && !c[y][0])
    	{
    		fa[y] = c[x][1] = 0;
    		pushup(x);
    	}
    }
    
    int main()
    {
    	//File("");
    	n = gi(), m = gi();
    	for (int i = 1; i <= n; i+=1) v[i] = gi();
    	while (m--)
    	{
    		int op = gi(), x = gi(), y = gi();
    		if (op == 0) split(x, y), printf("%d
    ", s[y]);
    		else if (op == 1) link(x, y);
    		else if (op == 2) cut(x, y);
    		else splay(x), v[x] = y;
    	}
    	return 0;
    }
    

    动态维护连通性

    例题:[SDOI2008]洞穴勘测

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 10003, M = N << 1;
    
    int n, m;
    int fa[N], stk[N], c[N][2];
    bool r[N];
    
    inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
    
    inline void pushr(int x) {swap(c[x][0], c[x][1]); r[x] ^= 1;}
    
    inline void pushdown(int x)
    {
    	if (r[x])
    	{
    		if (c[x][0]) pushr(c[x][0]);
    		if (c[x][1]) pushr(c[x][1]);
    		r[x] = 0;
    	}
    }
    
    inline void rotate(int x)
    {
    	int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
    	if (isroot(y)) c[z][c[z][1] == y] = x;
    	c[x][!k] = y, c[y][k] = w;
    	if (w) fa[w] = y;
    	fa[x] = z, fa[y] = x;
    }
    
    inline void splay(int x)
    {
    	int y = x, z = 0;
    	stk[z = 1] = y;
    	while (isroot(y)) stk[++z] = y = fa[y];
    	while (z) pushdown(stk[z--]);
    	while (isroot(x))
    	{
    		y = fa[x], z = fa[y];
    		if (isroot(y))
    			rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
    		rotate(x);
    	}
    }
    
    inline void access(int x)
    {
    	for (int y = 0; x; x = fa[y = x])
    		splay(x), c[x][1] = y;
    }
    
    inline void makeroot(int x)
    {
    	access(x); splay(x);
    	pushr(x);
    }
    
    inline int findroot(int x)
    {
    	access(x); splay(x);
    	while (c[x][0]) pushdown(x), x = c[x][0];
    	splay(x);
    	return x;
    }
    
    inline void link(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) != x) fa[x] = y;
    }
    
    inline void cut(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) == x && fa[y] == x && !c[y][0])
    	{
    		fa[y] = c[x][1] = 0;
    	}
    }
    
    int main()
    {
    	//File("");
    	n = gi(), m = gi();
    	while (m--)
    	{
    		char s[9];
    		scanf("%s", s);
    		int x = gi(), y = gi();
    		if (s[0] == 'C') link(x, y);
    		else if (s[0] == 'D') cut(x, y);
    		else
    		{
    			if (findroot(x) == findroot(y)) puts("Yes");
    			else puts("No");
    		}
    	}
    	return 0;
    }
    

    动态维护最小生成树

    例题:[WC2006]水管局长

    反过来操作,把删边变成加边。

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 1003, M = 200003, S = N + M;
    
    int n, m, q;
    struct Node
    {
    	int u, v, w;
    } a[S];
    struct Query
    {
    	int op, u, v;
    } b[M];
    int fa[S], c[S][2], val[S], id[S], stk[S], fat[S];
    bool r[S];
    
    inline bool cmp(Node x, Node y) {return x.w < y.w;}
    
    int getf(int u)
    {
    	if (fat[u] == u) return u;
    	return fat[u] = getf(fat[u]);
    }
    
    inline void unionn(int u, int v)
    {
    	int fu = getf(u), fv = getf(v);
    	if (fu != fv) fat[fu] = fat[fv];
    }
    
    inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
    
    inline void pushr(int x) {swap(c[x][0], c[x][1]), r[x] ^= 1;}
    
    inline void pushup(int x)
    {
    	id[x] = x;
    	if (c[x][0] && val[id[x]] < val[id[c[x][0]]]) id[x] = id[c[x][0]];
    	if (c[x][1] && val[id[x]] < val[id[c[x][1]]]) id[x] = id[c[x][1]];
    }
    
    inline void pushdown(int x)
    {
    	if (r[x])
    	{
    		if (c[x][0]) pushr(c[x][0]);
    		if (c[x][1]) pushr(c[x][1]);
    		r[x] = 0;
    	}
    }
    
    inline void rotate(int x)
    {
    	int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
    	if (isroot(y)) c[z][c[z][1] == y] = x;
    	c[x][!k] = y, c[y][k] = w;
    	if (w) fa[w] = y;
    	fa[x] = z, fa[y] = x;
    	pushup(y);
    }
    
    inline void splay(int x)
    {
    	int y = x, z = 0;
    	stk[z = 1] = y;
    	while (isroot(y)) stk[++z] = y = fa[y];
    	while (z) pushdown(stk[z--]);
    	while (isroot(x))
    	{
    		y = fa[x], z = fa[y];
    		if (isroot(y))
    			rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
    		rotate(x);
    	}
    	pushup(x);
    }
    
    inline void access(int x)
    {
    	for (int y = 0; x; x = fa[y = x])
    		splay(x), c[x][1] = y, pushup(x);
    }
    
    inline void makeroot(int x)
    {
    	access(x); splay(x);
    	pushr(x);
    }
    
    inline int findroot(int x)
    {
    	access(x); splay(x);
    	while (c[x][0]) pushdown(x), x = c[x][0];
    	splay(x);
    	return x;
    }
    
    inline void split(int x, int y)
    {
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    inline void link(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) != x) fa[x] = y;
    }
    
    inline void cut(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) == x && fa[y] == x && !c[y][0])
    	{
    		fa[y] = c[x][1] = 0;
    		pushup(x);
    	}
    }
    
    bool del[N][N];
    int z[N][N], kk[N][N];
    int ans[M];
    
    int main()
    {
    	n = gi(), m = gi(), q = gi();
    	for (int i = 1; i <= m; i+=1)
    	{
    		int u = gi(), v = gi(), t = gi();
    		a[i] = (Node){u, v, t};
    	}
    	sort(a + 1, a + 1 + m, cmp);
    	for (int i = 1; i <= m; i+=1)
    	{
    		val[i + n] = a[i].w;
    		int u = a[i].u, v = a[i].v;
    		z[u][v] = z[v][u] = a[i].w;
    		kk[u][v] = kk[v][u] = i;
    	}
    	for (int i = 1; i <= n + m; i+=1) id[i] = fat[i] = i;
    	for (int i = 1; i <= q; i+=1)
    	{
    		int op = gi(), u = gi(), v = gi();
    		b[i] = (Query){op, u, v};
    		if (op == 2) del[u][v] = del[v][u] = true;
    	}
    	for (int i = 1; i <= m; i+=1)
    	{
    		if (del[a[i].u][a[i].v]) continue;
    		int fx = getf(a[i].u), fy = getf(a[i].v);
    		if (fx != fy)
    			unionn(fx, fy), link(i + n, a[i].u), link(i + n, a[i].v);
    		else
    		{
    			split(a[i].u, a[i].v);
    			int mx = id[a[i].v];
    			if (a[i].w < val[mx])
    				cut(mx, a[mx - n].u), cut(mx, a[mx - n].v),
    			    link(i + n, a[i].u), link(i + n, a[i].v);
    		}
    	}
    	for (int i = q; i >= 1; i-=1)
    		if (b[i].op == 1)
    		{
    			split(b[i].u, b[i].v);
    			ans[i] = val[id[b[i].v]];
    		}
    		else
    		{
    			int fx = getf(b[i].u), fy = getf(b[i].v);
    			if (fx != fy)
    				unionn(fx, fy), link(kk[b[i].u][b[i].v] + n, b[i].u), link(kk[b[i].u][b[i].v] + n, b[i].v);
    			else
    			{
    				split(b[i].u, b[i].v);
    				int mx = id[b[i].v];
    				if (z[b[i].u][b[i].v] < val[mx])
    					cut(mx, a[mx - n].u), cut(mx, a[mx - n].v),
    					link(kk[b[i].u][b[i].v] + n, b[i].u), link(kk[b[i].u][b[i].v] + n, b[i].v);
    			}
    		}
    	for (int i = 1; i <= q; i+=1)
    		if (b[i].op == 1) printf("%d
    ", ans[i]);
    	return 0;
    }
    

    例题:[NOI2014]魔法森林

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 50003, M = N << 1, S = N + M;
    
    int n, m;
    int fa[S], c[S][2], mn[S], stk[S], val[S], id[S], fat[S];
    int tot;
    bool r[S];
    int ans = INF;
    struct Node
    {
    	int x, y, a, b;
    } a[S];
    
    int getf(int x)
    {
    	if (fat[x] == x) return x;
    	return fat[x] = getf(fat[x]);
    }
    
    inline void unionn(int x, int y)
    {
    	int ux = getf(x), uy = getf(y);
        fat[ux] = uy;
    }
    
    inline bool cmp(Node x, Node y)
    {
    	if (x.a != y.a) return x.a < y.a;
    	return x.b < y.b;
    }
    
    inline bool isroot(int x) {return c[fa[x]][0] == x || c[fa[x]][1] == x;}
    
    inline void pushr(int x) {swap(c[x][1], c[x][0]), r[x] ^= 1;}
    
    inline void pushup(int x)
    {
    	id[x] = x;
    	if (c[x][0] && val[id[x]] < val[id[c[x][0]]]) id[x] = id[c[x][0]];
    	if (c[x][1] && val[id[x]] < val[id[c[x][1]]]) id[x] = id[c[x][1]];    
    }
    
    inline void pushdown(int x)
    {
    	if (r[x])
    	{
    		if (c[x][0]) pushr(c[x][0]);
    		if (c[x][1]) pushr(c[x][1]);
    		r[x] = 0;
    	}
    }
    
    inline void rotate(int x)
    {
    	int y = fa[x], z = fa[y], k = (c[y][1] == x), w = c[x][!k];
    	if (isroot(y)) c[z][c[z][1] == y] = x;
    	c[y][k] = w, c[x][!k] = y;
    	if (w) fa[w] = y;
    	fa[x] = z, fa[y] = x;
    	pushup(y);
    }
    
    inline void splay(int x)
    {
    	int y = x, z = 0;
    	stk[z = 1] = y;
    	while (isroot(y)) stk[++z] = y = fa[y];
    	while (z) pushdown(stk[z--]);
    	while (isroot(x))
    	{
    		y = fa[x], z = fa[y];
    		if (isroot(y))
    			rotate(((c[z][1] == y) ^ (c[y][1] == x)) ? x : y);
    		rotate(x);
    	}
    	pushup(x);
    }
    
    inline void access(int x)
    {
    	for (int y = 0; x; x = fa[y = x])
    		splay(x), c[x][1] = y, pushup(x);
    }
    
    inline void makeroot(int x)
    {
    	access(x); splay(x);
    	pushr(x);
    }
    
    inline int findroot(int x)
    {
    	access(x); splay(x);
    	while (c[x][0]) pushdown(x), x = c[x][0];
    	splay(x);
    	return x;
    }
    
    inline void split(int x, int y)
    {
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    inline void link(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) != x) fa[x] = y;
    }
    
    inline void cut(int x, int y)
    {
    	makeroot(x);
    	if (findroot(y) == x && fa[y] == x && !c[y][0])
    	{
    		fa[y] = c[x][1] = 0;
    		pushup(x);
    	}
    }
    
    int main()
    {
    	//File("");
    	n = gi(), m = gi();
    	for (int i = 1; i <= m; i+=1)
    	{
    		int x = gi(), y = gi(), aa = gi(), b = gi();
    		if (x == y) continue;
    		a[++tot] = (Node){x, y, aa, b};
    	}
    	for (int i = 1; i <= n + tot; i+=1) fat[i] = id[i] = i;
    	sort(a + 1, a + 1 + tot, cmp);
    	for (int i = 1; i <= tot; i+=1) val[i + n] = a[i].b;
    	for (int i = 1; i <= tot; i+=1)
    	{
    		int fx = getf(a[i].x), fy = getf(a[i].y);
    		if (fx != fy) unionn(fx, fy), link(i + n, a[i].x), link(i + n, a[i].y);
    		else
    		{
    			split(a[i].x, a[i].y);
    			int mx = id[a[i].y];
    			if (a[i].b < val[mx])
    				cut(mx, a[mx - n].x), cut(mx, a[mx - n].y), link(i + n, a[i].x), link(i + n, a[i].y);
    		}
    		if (getf(1) == getf(n))
    		{
    			split(1, n);
    			ans = min(ans, a[i].a + val[id[n]]);
    		}
    	}
    	if (ans == INF) puts("-1");
    	else printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    使用init_connect记录MySQL登录日志
    MySQL 在线开启GTID的每个阶段是要做什么
    chrome控制台发送post请求
    口语练习
    adb_usb.ini在adb找不到设备时
    ubuntu 12.04硬盘分区,格式化,挂载
    编译错误处理noproguard.classeswithlocal.dex已杀死
    ubuntu 12.04(gcc降级)编译android代码遇到"_FORTIFY_SOURCE"的解决方法
    ubuntu在update的时候报错GPL ERROR
    工作站环境搭建
  • 原文地址:https://www.cnblogs.com/xsl19/p/13513663.html
Copyright © 2020-2023  润新知