[HEOI2016/TJOI2016]树

时间:2021-08-11
本文章向大家介绍[HEOI2016/TJOI2016]树,主要包括[HEOI2016/TJOI2016]树使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[HEOI2016/TJOI2016]树

这是一道树剖板子题,所以我们没什么讲的

洛谷题目链接


题解

我们用线段树维护树剖序上的\(sum\)值,即为染色的数量的\(sum\),当\(sum=0\)时,从\(x\)节点向上爬树,当我们查询到这条链的\(sum>=1\)​​时二分答案即可。


#include<bits/stdc++.h>
using namespace std;
const int MN=1e5+100;
int n,q;
int head[MN],cnt;
struct node{
	int nxt,to;
}e[MN<<1];
inline void add(int a,int b){e[++cnt].nxt=head[a],head[a]=cnt,e[cnt].to=b;}
int son[MN],siz[MN],fa[MN],dep[MN];
void dfs1(int now,int pre){
	dep[now]=dep[pre]+1,fa[now]=pre,siz[now]=1;
	for(int i=head[now];i;i=e[i].nxt){
		int to=e[i].to;
		if(to==pre)continue;
		dfs1(to,now);
		siz[now]+=siz[to];
		if(siz[to]>siz[son[now]])son[now]=to;
	}
}
int dfn[MN],top[MN],tot,name[MN];
void dfs2(int now,int tp){
	top[now]=tp,dfn[now]=++tot,name[tot]=now;
	if(son[now])dfs2(son[now],tp);
	for(int i=head[now];i;i=e[i].nxt){
		int to=e[i].to;
		if(to==fa[now]||to==son[now])continue;
		dfs2(to,to);
	}
}
#define lc id<<1
#define rc id<<1|1
struct tree{
	int l,r,sum;
}t[MN<<2];
void pushup(int id){
	t[id].sum=t[lc].sum+t[rc].sum;
}
void build(int id,int l,int r){
	t[id].l=l,t[id].r=r;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(lc,l,mid),build(rc,mid+1,r);
}
void change(int id,int k){
	if(t[id].l==t[id].r&&t[id].l==k){
		t[id].sum=1;
		return;
	}
	int mid=(t[id].l+t[id].r)>>1;
	if(k<=mid)change(lc,k);
	else change(rc,k);
	pushup(id);
}
int get_sum(int id,int l,int r){
	if(t[id].l>=l&&t[id].r<=r)return t[id].sum;
	int mid=(t[id].l+t[id].r)>>1,ans=0;
	if(l<=mid)ans+=get_sum(lc,l,r);
	if(r>=mid+1)ans+=get_sum(rc,l,r);
	return ans;
}
int lower(int l,int r){
	if(l==r)return name[l];
	int mid=(l+r)>>1;
	if(get_sum(1,mid+1,r))return lower(mid+1,r);
	else return lower(l,mid);
}
int query(int x){
	int ans=0;
	while(!ans){
		int sum=0;
		sum=get_sum(1,dfn[top[x]],dfn[x]);
		if(sum){
			ans=lower(dfn[top[x]],dfn[x]);
		}
		else x=fa[top[x]];
	}
	return ans;
}
int main(){
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	scanf("%d%d",&n,&q);
	for(int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u);
	dfs1(1,0);dfs2(1,1);build(1,1,n);change(1,dfn[1]);
	int x;char s;
	while(q--){
		scanf("%s%d",&s,&x);
		if(s=='Q')printf("%d\n",query(x));
		else change(1,dfn[x]);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/fanner-Blog/p/15129277.html