zoukankan      html  css  js  c++  java
  • LOJ #2092. 「ZJOI2016」大森林(lct)

    https://loj.ac/problem/2092

    题解:

    • 因为保证询问合法,所以可以把询问放到最后去询问

    • 0操作可以视作对([1,n])的树都操作,但是在1操作时,因为没有(x)的树不换生长节点,所以要和对应0操作的区间取交。

    • 设1操作的区间取交是[l,r],若从左往右考虑每个树,发现(tree[l])(tree[l-1])的区别就是把之前生长节点的子树复制到(x)下面,r同理。

    • 所以不难想到ETT暴力维护,但是可以建虚点,把一个生长节点的子树放到它的虚点下,虚点再指向它,这样就可以用lct维护了。

    • 注意到两个点的lca可能是一个虚点,这可能会对答案产生影响,因此lct要不换根的以求lca。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 4e5 + 5;
    
    int n, m;
    int td, tt;
    int op, x, y, z;
    int L[N], R[N];
    #define pii pair<int, int>
    #define pb push_back
    #define si size()
    
    namespace lct {
    	int t[N][2], fa[N], pf[N], s[N], z[N];
    	#define x0 t[x][0]
    	#define x1 t[x][1]
    	int lr(int x) { return t[fa[x]][1] == x;}
    	void upd(int x) {
    		s[x] = z[x] + s[x0] + s[x1];
    	}
    	void ro(int x) {
    		int y = fa[x], k = lr(x);
    		t[y][k] = t[x][!k]; if(t[x][!k]) fa[t[x][!k]] = y;
    		fa[x] = fa[y]; if(fa[y]) t[fa[y]][lr(y)] = x;
    		fa[y] = x, t[x][!k] = y, pf[x] = pf[y];
    		upd(y); upd(x);
    	}
    	void sp(int x, int y) {
    		for(; fa[x] != y; ro(x)) if(fa[fa[x]] != y)
    			ro(lr(x) == lr(fa[x]) ? fa[x] : x);
    	}
    	void ac(int x) {
    		int xx = x;
    		for(int y = 0; x; ) {
    			sp(x, 0), fa[x1] = 0, pf[x1] = x;
    			x1 = y, fa[y] = x, pf[y] = 0;
    			upd(x), y = x, x = pf[x];
    		}
    		sp(xx, 0);
    	}
    	void link(int x, int y) {
    		ac(x); pf[x] = y;
    	}
    	void cut(int x) {
    		ac(x);
    		int y = x0;
    		fa[y] = x0 = 0;
    		upd(x);
    	}
    	int lca(int u, int v) {
    		ac(u);
    		int la = v;
    		for(int x = v, y = 0; x; ) {
    			sp(x, 0), fa[x1] = 0, pf[x1] = x;
    			x1 = y, fa[y] = x, pf[y] = 0;
    			upd(x), y = x, x = pf[x];
    			if(x) la = x;
    		}
    		return la;
    	}
    	int findv(int x) {
    		ac(x);
    		return s[x];
    	}
    	int qry(int u, int v) {
    		int w = lca(u, v);
    		return findv(u) + findv(v) - 2 * findv(w) + 1;
    	}
    }
    
    struct nod {
    	int x, y, z;		
    };
    
    vector<nod> e[N], q[N];
    int q0;
    
    void Init() {
    	scanf("%d %d", &n, &m);
    	fo(i, 1, m) lct :: z[i] = lct :: z[i] = 1;
    	L[1] = 1, R[1] = n;
    	td = 1; tt = m + 2;
    	int la = tt;
    	lct :: link(la, 1);
    	fo(i, 1, m) {
    		scanf("%d %d %d", &op, &x, &y);
    		if(op == 0) {
    			td ++;
    			L[td] = x, R[td] = y;
    			lct :: link(td, la);
    		} else
    		if(op == 1) {
    			scanf("%d", &z);
    			
    			x = max(x, L[z]);
    			y = min(y, R[z]);
    			
    			if(x > y) continue;
    			tt ++;
    			lct :: link(tt, la);
    			
    			e[x].pb((nod) {tt, la, z});
    			e[y + 1].pb((nod) {tt, z, la});
    			
    			la = tt;
    		} else {
    			scanf("%d", &z);
    			q0 ++;
    			q[x].pb((nod) {y, z, q0});
    		}
    	}
    }
    
    int ans[N];
    
    void End() {
    	fo(i, 1, n) {
    		ff(_j, 0, e[i].si) {
    			nod a = e[i][_j];
    			lct :: cut(a.x);
    			lct :: link(a.x, a.z);
    		}
    		ff(_j, 0, q[i].si) {
    			nod a = q[i][_j];
    			ans[a.z] = lct :: qry(a.x, a.y);
    		}
    	}
    	fo(i, 1, q0) pp("%d
    ", ans[i] - 1);
    }
    
    int main() {
    	Init();
    	End();
    }
    
  • 相关阅读:
    【刷题】UOJ #274 【清华集训2016】温暖会指引我们前行
    【刷题】BZOJ 3669 [Noi2014]魔法森林
    【刷题】BZOJ 2594 [Wc2006]水管局长数据加强版
    (84)Wangdao.com第十八天_JavaScript 文档对象模型 DOM
    (84)Wangdao.com第十八天_JavaScript Promise 对象
    (83)Wangdao.com第十七天_JavaScript 定时器
    (82)Wangdao.com第十六天_JavaScript 异步操作
    (81)Wangdao.com第十六天_JavaScript 严格模式
    (80)Wangdao.com第十六天_JavaScript Object 对象的相关方法
    (79)Wangdao.com第十五天_JavaScript 对象的继承_prototype原型对象_封装_函数式编程
  • 原文地址:https://www.cnblogs.com/coldchair/p/13035907.html
Copyright © 2011-2022 走看看