• Bzoj4573: [Zjoi2016]大森林


    题面

    传送门

    Sol

    我太菜了,有点思维的题根本不会

    (sto HJT)

    考虑一个(1)操作,相当于是(l-1)(l)处长节点的位置不同了
    那么在(l-1)处长,然后接在(l)就好了
    (r)(r+1)同理

    考虑怎么来做
    虚点的思想
    维护一个全局的树,上面有虚点和实点
    每次(0)操作直接长实点(link)
    (1)操作就新建虚点,接在原来的虚点上
    这样利用上面的思想
    对于(1)操作,只要在(l-1)处,把当前生长节点的整个子树接在(l)(x)
    然后再在(r)(r+1)时接回来就能表示出每棵树了

    那么把操作(1)拆成两个,(l)(r+1)
    按端点(sort)就能表示了

    考虑询问,首先直接把一棵树建完后再查询是没有影响的
    那么每次到一棵树,做完所有操作就可以询问了
    给每个点赋权值,实点为(1),虚点为(0)

    (LCT)(u, v)(lca)
    (Access(u)),然后(Access(y))遇到的最后一条虚边上面的点就是(lca)
    求路径长度,就是(1)(u)的权值和+(1)(v)的-(2*1)(lca)

    (HJT orz)

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    
    template <class Int>
    IL void Input(RG Int &x){
        RG int z = 1; RG char c = getchar(); x = 0;
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        x *= z;
    }
    
    const int maxn(3e5 + 5);
    
    int fa[maxn], ch[2][maxn], sum[maxn], val[maxn];
    
    IL int Son(RG int x){
    	return ch[1][fa[x]] == x;
    }
    
    IL int Isroot(RG int x){
    	return ch[0][fa[x]] != x && ch[1][fa[x]] != x;
    }
    
    IL void Update(RG int x){
    	sum[x] = val[x] + sum[ch[0][x]] + sum[ch[1][x]];
    }
    
    IL void Rotate(RG int x){
    	RG int y = fa[x], z = fa[y], c = Son(x);
    	if(!Isroot(y)) ch[Son(y)][z] = x; fa[x] = z;
    	ch[c][y] = ch[!c][x], fa[ch[c][y]] = y;
    	ch[!c][x] = y, fa[y] = x;
    	Update(y);
    }
    
    IL void Splay(RG int x){
    	for(RG int y = fa[x]; !Isroot(x); Rotate(x), y = fa[x])
    		if(!Isroot(y)) Son(x) ^ Son(y) ? Rotate(x) : Rotate(y);
    	Update(x);
    }
    
    IL int Access(RG int x){
    	RG int y = 0;
    	for(; x; y = x, x = fa[x]) Splay(x), ch[1][x] = y, Update(x);
    	return y;
    }
    
    IL void Cut(RG int x){
    	Access(x), Splay(x), ch[0][x] = fa[ch[0][x]] = 0, Update(x);
    }
    
    int n, m, id[maxn], num, tot, ql[maxn], qr[maxn], q, ans[maxn], now, cnt;
    
    struct Query{
    	int pos, x, y, id;
    
    	IL int operator <(RG Query B) const{
    		return pos != B.pos ? pos < B.pos : id < B.id;
    	}
    } qry[maxn];
    
    int main(RG int argc, RG char* argv[]){
    	Input(n), Input(m);
    	id[1] = ql[1] = 1, qr[1] = n;
    	num = tot = val[1] = 1;
    	fa[now = ++tot] = 1;
    	for(RG int i = 1, op, l, r, x; i <= m; ++i){
    		Input(op), Input(l), Input(r);
    		if(op == 1){
    			Input(x), l = max(l, ql[x]), r = min(r, qr[x]);
    			if(l > r) continue;
    			fa[++tot] = now;
    			qry[++cnt] = (Query){l, tot, id[x], 0};
    			qry[++cnt] = (Query){r + 1, tot, now, 0};
    			now = tot;
    		}
    		else if(op == 0){
    			val[++tot] = 1;
    			fa[id[++num] = tot] = now;
    			ql[num] = l, qr[num] = r;
    		}
    		else Input(x), qry[++cnt] = (Query){l, id[r], id[x], ++q};
    	}
    	sort(qry + 1, qry + cnt + 1);
    	for(RG int i = 1, lca; i <= cnt; ++i)
    		if(qry[i].id){
    			Access(qry[i].x), Splay(qry[i].x), ans[qry[i].id] += sum[qry[i].x];
    			lca = Access(qry[i].y), Splay(qry[i].y), ans[qry[i].id] += sum[qry[i].y];
    			Access(lca), Splay(lca), ans[qry[i].id] -= (sum[lca] << 1);
    		}
    		else Cut(qry[i].x), fa[qry[i].x] = qry[i].y;
    	for(RG int i = 1; i <= q; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    
    
  • 相关阅读:
    凸松弛技术解密
    机器学习中的逻辑回归模型简介
    机器学习中的损失函数
    逻辑回归的MATLAB实现(二分类问题)
    Lua和C++交互详细总结【转载】
    微擎手机端上传视频(图片)
    IOS开发:UIAlertView使用
    高度自适应问题
    css样式问题
    browser-sync
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8763211.html
Copyright © 2020-2023  润新知