关闭

bzoj 4551: [Tjoi2016&Heoi2016]树 并查集

203人阅读 评论(0) 收藏 举报
分类:

题意:有一棵树,一开始根节点是黑色的,其余节点都是白色的。要求资瓷两个操作:

给某个节点变成黑色

查询离某个节点最近的祖先


分析:一开始往各种数据结构和神奇的算法上面去想但都没卵用,也想过离线,但感觉貌似不行就pass了。结果正解真的是离线搞……

以后有想法后一定要仔细想清楚是否能行。

正解其实就是从后往前搞然后用并查集维护一下就好了。

一次AC不解释


代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;

int n,m,f[N],fa[N],ans[N],x[N],last[N],cnt,tag[N];
char ch[N][2];
struct edge{int to,next;}e[N*2];

void insert(int u,int v)
{
	e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
	e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}

int find(int x)
{
	if (f[x]==x) return x;
	f[x]=find(f[x]);
	return f[x];
}

void dfs(int x,int p)
{
	if (x!=p) f[find(x)]=find(p);
	for (int i=last[x];i;i=e[i].next)
	{
		if (e[i].to==fa[x]) continue;
		fa[e[i].to]=x;
		if (tag[e[i].to]) dfs(e[i].to,e[i].to);
		else dfs(e[i].to,p);
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		insert(u,v);
	}
	tag[1]++;
	for (int i=1;i<=m;i++)
	{
		scanf("%s%d",&ch[i],&x[i]);
		if (ch[i][0]=='C') tag[x[i]]++;
	}
	for (int i=1;i<=n;i++)
		f[i]=i;
	dfs(1,1);
	for (int i=m;i>=1;i--)
		if (ch[i][0]=='C')
		{
			tag[x[i]]--;
			if (!tag[x[i]]) f[find(x[i])]=find(fa[x[i]]);
		}
		else ans[i]=find(x[i]);
	for (int i=1;i<=m;i++)
		if (ch[i][0]=='Q') printf("%d\n",ans[i]);
	return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:144508次
    • 积分:10243
    • 等级:
    • 排名:第1787名
    • 原创:920篇
    • 转载:13篇
    • 译文:0篇
    • 评论:31条
    欢迎qq交流
    qq:763647200
    友情链接
    文章分类
    最新评论