• loj2001 「SDOI2017」树点涂色


    there

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int n, m, dfn[100005], idx, hea[100005], cnt, uu, vv, siz[100005], fa[100005][19];
    int dep[100005], val[400005], dui[100005], opt, ch[100005][2], tag[400005];
    int af[100005];
    struct Edge{
    	int too, nxt;
    }edge[200005];
    void add_edge(int fro, int too){
    	edge[++cnt].nxt = hea[fro];
    	edge[cnt].too = too;
    	hea[fro] = cnt;
    }
    bool isRoot(int x){
    	return ch[af[x]][0]!=x && ch[af[x]][1]!=x;
    }
    bool getW(int x){
    	return ch[af[x]][1]==x;
    }
    void dfs(int x, int f){
    	fa[x][0] = f;
    	af[x] = f;
    	dep[x] = dep[f] + 1;
    	dfn[x] = ++idx;
    	dui[idx] = dep[x];
    	siz[x] = 1;
    	for(int i=1; i<=16; i++)
    		fa[x][i] = fa[fa[x][i-1]][i-1];
    	for(int i=hea[x]; i; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(t!=f){
    			dfs(t, x);
    			siz[x] += siz[t];
    		}
    	}
    }
    void build(int o, int l, int r){
    	if(l==r)	val[o] = dui[l];
    	else{
    		int mid=(l+r)>>1;
    		int lson=o<<1;
    		int rson=lson|1;
    		if(l<=mid)	build(lson, l, mid);
    		if(mid<r)	build(rson, mid+1, r);
    		val[o] = max(val[lson], val[rson]);
    	}
    }
    void rotate(int x){
    	int old=af[x], oldf=af[old], w=getW(x);
    	if(!isRoot(old))	ch[oldf][ch[oldf][1]==old] = x;
    	ch[old][w] = ch[x][w^1]; ch[x][w^1] = old;
    	af[ch[old][w]] = old; af[ch[x][w^1]] = x; af[x] = oldf;
    }
    void splay(int x){
    	while(!isRoot(x)){
    		int f=af[x];
    		if(!isRoot(f))	rotate(getW(f)==getW(x)?f:x);
    		rotate(x);
    	}
    }
    int findRoot2(int x){
    	while(ch[x][0])	x = ch[x][0];
    	return x;
    }
    void sgtPushDown(int o, int l, int r, int lson, int rson, int mid){
    	val[lson] += tag[o];
    	val[rson] += tag[o];
    	tag[lson] += tag[o];
    	tag[rson] += tag[o];
    	tag[o] = 0;
    }
    void update(int o, int l, int r, int x, int y, int k){
    	if(l>=x && r<=y){
    		val[o] += k;
    		tag[o] += k;
    	}
    	else{
    		int mid=(l+r)>>1;
    		int lson=o<<1;
    		int rson=lson|1;
    		if(tag[o])	sgtPushDown(o, l, r, lson, rson, mid);
    		if(x<=mid)	update(lson, l, mid, x, y, k);
    		if(mid<y)	update(rson, mid+1, r, x, y, k);
    		val[o] = max(val[lson], val[rson]);
    	}
    }
    void access(int x){
    	int y=0;
    	while(x){
    		splay(x);
    		if(ch[x][1]){
    			int t=findRoot2(ch[x][1]);
    			update(1, 1, n, dfn[t], dfn[t]+siz[t]-1, 1);
    		}
    		ch[x][1] = y;
    		if(ch[x][1]){
    			int t=findRoot2(ch[x][1]);
    			update(1, 1, n, dfn[t], dfn[t]+siz[t]-1, -1);
    		}
    		y = x;
    		x = af[x];
    	}
    }
    int getLca(int u, int v){
    	if(dep[u]<dep[v])	swap(u, v);
    	for(int i=16; i>=0; i--)
    		if(dep[fa[u][i]]>=dep[v])
    			u = fa[u][i];
    	if(u==v)	return u;
    	for(int i=16; i>=0; i--)
    		if(fa[u][i]!=fa[v][i]){
    			u = fa[u][i];
    			v = fa[v][i];
    		}
    	return fa[u][0];
    }
    int query(int o, int l, int r, int x, int y){
    	if(l>=x && r<=y)	return val[o];
    	else{
    		int mid=(l+r)>>1;
    		int lson=o<<1;
    		int rson=lson|1;
    		int ans=0;
    		if(tag[o])	sgtPushDown(o, l, r, lson, rson, mid);
    		if(x<=mid)	ans = max(ans, query(lson, l, mid, x, y));
    		if(mid<y)	ans = max(ans, query(rson, mid+1, r, x, y));
    		return ans;
    	}
    }
    int main(){
    	cin>>n>>m;
    	for(int i=1; i<n; i++){
    		scanf("%d %d", &uu, &vv);
    		add_edge(uu, vv);
    		add_edge(vv, uu);
    	}
    	dfs(1, 0);
    	build(1, 1, n);
    	while(m--){
    		scanf("%d", &opt);
    		if(opt==1){
    			scanf("%d", &uu);
    			access(uu);
    		}
    		else if(opt==2){
    			scanf("%d %d", &uu, &vv);
    			int lca=getLca(uu, vv);
    			printf("%d
    ", query(1, 1, n, dfn[uu], dfn[uu])+query(1, 1, n, dfn[vv], dfn[vv])-2*query(1, 1, n, dfn[lca], dfn[lca])+1);
    		}
    		else{
    			scanf("%d", &uu);
    			printf("%d
    ", query(1, 1, n, dfn[uu], dfn[uu]+siz[uu]-1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何去掉视频四周的黑边,使之充满整个屏幕?
    EMQX 入门实战(2)MQTT Java 客户端库使用
    Elasticsearch 入门实战(1)简介
    EMQX 入门实战(1)安装及简单使用
    浅聊Mybatis是怎么扫描并且注入到spring容器中的(源码向)
    Docker安装常用服务命令笔记
    Java中Stream相关常用总结记录
    注解和自定义注解
    集合框架ArrayList学习和总结
    不定长可重复字符组合枚举递归函数
  • 原文地址:https://www.cnblogs.com/poorpool/p/8810179.html
Copyright © 2020-2023  润新知