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;
}
原文地址:https://www.cnblogs.com/poorpool/p/8810179.html