• loj#121.「离线可过」动态图连通性


    题面

    话说#122怎么做啊

    题解

    我的(mathrm{LCT})水平极差,连最小生成树都快忘了,赶紧复习一下

    做法和这篇是一样的

    这道题还可以练习线段树分治

    还可以练习ETT

    果然是道吼题

    代码

    LCT

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<map>
    #define RG register
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define clear(x, y) memset(x, y, sizeof(x))
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(505010), INF(0x3f3f3f3f);
    struct edge { int opt, from, to, beg, end; } e[maxn];
    int n, m, val[maxn], fa[maxn], son[2][maxn];
    int stk[maxn], top, del[maxn], cnt, tim;
    bool rev[maxn]; std::map<int, int> G[maxn];
    
    inline bool isroot(int x) { return son[0][fa[x]] != x && son[1][fa[x]] != x; }
    inline int getson(int x) { return son[1][fa[x]] == x; }
    inline void update(int x)
    {
    	del[x] = x;
    	if(val[del[x]] > val[del[son[0][x]]]) del[x] = del[son[0][x]];
    	if(val[del[x]] > val[del[son[1][x]]]) del[x] = del[son[1][x]];
    }
    
    inline void pushdown(int x)
    {
    	if(!rev[x]) return;
    	rev[son[0][x]] ^= 1;
    	rev[son[1][x]] ^= 1;
    	rev[x] = 0, std::swap(son[0][x], son[1][x]);
    }
    
    inline void rotate(int x)
    {
    	int f = fa[x], g = fa[f], l = getson(x), r = l ^ 1;
    	if(!isroot(f)) son[getson(f)][g] = x;
    	fa[x] = g, fa[f] = x, fa[son[r][x]] = f;
    	son[l][f] = son[r][x], son[r][x] = f;
    	update(f); update(x);
    }
    
    void splay(int x)
    {
    	stk[top = 1] = x;
    	for(RG int i = x; !isroot(i); i = fa[i]) stk[++top] = fa[i];
    	for(RG int i = top; i; i--) pushdown(stk[i]);
    	for(; !isroot(x); rotate(x)) if(!isroot(fa[x]))
    		rotate(getson(fa[x]) ^ getson(x) ? x : fa[x]);
    }
    
    void access(int x)
    {
    	for(RG int t = 0; x; t = x, x = fa[x])
    		splay(x), son[1][x] = t, update(x);
    }
    
    int find(int x) { access(x); splay(x); while(son[0][x]) x = son[0][x]; return x; }
    inline void makeroot(int x) { access(x); splay(x); rev[x] ^= 1; }
    inline void split(int x, int y) { makeroot(x); access(y); splay(y); }
    inline void link(int x, int y) { makeroot(x); fa[x] = y; }
    inline void cut(int x, int y) { split(x, y); son[0][y] = fa[x] = 0; update(y); }
    
    int main()
    {
    	cnt = n = read(), m = read();
    	for(RG int i = 1; i <= m; i++)
    	{
    		int opt = read(), x = read(), y = read();
    		if(x > y) std::swap(x, y);
    		++tim;
    		if(opt == 0) e[G[x][y] = tim].end = INF;
    		if(opt == 1) e[G[x][y]].end = tim;
    		e[tim].beg = tim, e[tim].opt = opt, e[tim].from = x, e[tim].to = y;
    	}
    	for(RG int i = 0; i <= cnt; i++) val[i] = INF;
    	for(RG int i = 1; i <= tim; i++)
    	{
    		int x1 = e[i].from, x2 = e[i].to;
    		if(e[i].opt == 0)
    		{
    			if(x1 == x2) continue;
    			if(find(x1) == find(x2))
    			{
    				split(x1, x2); int d = del[x2];
    				if(val[d] >= e[i].end) continue;
    				else cut(x1, d), cut(x2, d);
    				val[++cnt] = e[i].end;
    				link(x1, cnt), link(x2, cnt);
    			}
    			else val[++cnt] = e[i].end, link(x1, cnt), link(x2, cnt);
    		}
    		if(e[i].opt == 1)
    		{
    			if(find(x1) == find(x2))
    			{
    				split(x1, x2); int d = del[x2];
    				if(val[d] > e[i].beg) continue;
    				cut(x1, d), cut(x2, d);
    			}
    		}
    		if(e[i].opt == 2) puts(find(x1) == find(x2) ? "Y" : "N");
    	}
    	return 0;
    }
    

    线段树分治

    咕咕咕

  • 相关阅读:
    hibernate建表默认为UTF-8编码
    XML和JSON
    chrome 模拟发送请求的方法
    什么时候需要使用缓存?
    eclipse中查找类、方法及变量被引用的地方
    用户内容与商业
    2019第48周日
    ajax与重定向
    ifream
    Windows下找到JVM占用资源高的线程
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10340545.html
Copyright © 2020-2023  润新知