列表

详情


NC15509. 一级棒!

描述

ACSquare只会玩很休闲很休闲的音游(比如节奏地牢),像跳舞这种重度的东西就基本无能为力了。幸运的是,他的舞伴很熟练,这成功地显得他更加咸鱼。他所在场地可以被视为是一棵有N个节点的“树“(图论意义上),他们在”树”上沿着“边”移动。ACSquare认为有且经过一次的”边“,是“一级棒的边“,于是他开始思考哪些边是“一级棒的边”。可惜的是,陷入了中年危机的他,已经记不住之前经过哪些的“边”了。现在他想请你帮忙,根据他的回忆来逐步回答树上的边被经过的信息。


输入描述

输入包含多组数据,请处理到文件结束。
每组数据,第一行是一个正整数 N (2<= N <= 100,000)表示树的节点个数;
第二行包括N-1个数,其中第i个数{pi},表示节点 i 的父节点编号为pi(pi < i)(节点编号从0开始);
第三行是一个正整数Q(1<=Q<=200,000);
接下来的Q行有两种形式的命令
1. R u v , 表示ACSquare想起已经经过了u,v(编号从0开始)间的路径一次,
2. W v, 表示ACSquare想让你根据他想起的信息,回答(v,pv),(v与pv间的边,其中v != 0),即根据目前给出的 1 形式的信息,回答边被经过的相关信息。

输出描述

对于每个第二中形式的命令,做出回答。
1.若(v,pv),还未被经过,则回答"Not yet";
2.若(v,pv),恰好是“一级棒的边”,回答恰好经过这条边的路径端点,按升序在一行内输出;
3.若(v,pv),被超过一次经过,则回答"Many times"。
注意,若多次想起同一对点对,应该当做不同的路径对来处理。

示例1

输入:

5
0 1 1 3
5
R 2 1
W 4
W 2
R 4 2
W 2

输出:

Not yet
1 2
Many times

说明:

海量数据,免费测试,脱非入欧,在此一举!

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 550ms, 内存消耗: 17384K, 提交时间: 2020-04-19 16:58:09

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=(int)1e5+10;
int par[maxn],dep[maxn],num[maxn],s[maxn],t[maxn],far[maxn];
char op[2];
inline int Find(int x)
{
	return par[x]==x?x:par[x]=Find(par[x]);
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		for(int i=1;i<n;++i)
		{
			scanf("%d",&far[i]);
			num[i]=0;
			par[i]=i;
			dep[i]=dep[far[i]]+1;
		}
		int q,u,v,x,y;
		scanf("%d",&q);
		while(q--)
		{
			scanf("%s",op);
			if(op[0]=='R')
			{
				scanf("%d%d",&u,&v);
				x=u;
				y=v;
				while(x!=y)
				{
					if(dep[x]<dep[y])
					{
						swap(x,y);
					}
					if((++num[x])<=1)
					{
						s[x]=min(u,v);
						t[x]=max(u,v);
					}
					else
					{
						par[x]=far[x];
					}
					x=Find(far[x]);
				}
			}
			else
			{
				scanf("%d",&u);
				if(num[u]==0)
				{
					puts("Not yet");
				}
				else if(num[u]==1)
				{
					printf("%d %d\n",s[u],t[u]);
				}
				else
				{
					puts("Many times");
				}
			}
		}
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 695ms, 内存消耗: 7700K, 提交时间: 2019-11-01 08:04:50

#include<iostream>
#include<stdio.h>
using namespace std;
const int N=1e5+10;
int fa[N],f[N],cnt[N],dep[N],l[N],r[N];
int find(int x) {
	if(f[x]==x)return x;
	return f[x]=find(f[x]);
}
int main() {
	char s[2];
	int n,i,q,x,y;
	while(~scanf("%d",&n)) {
		for(i=1; i<n; ++i) {
			scanf("%d",&fa[i]);
			dep[i]=dep[fa[i]]+1;
			f[i]=i,cnt[i]=0;
		}
		scanf("%d",&q);
		while(q--) {
			scanf("%s",s);
			if(s[0]=='R') {
				scanf("%d%d",&x,&y);
				if(x>y)swap(x,y);
				int u=x,v=y;
				while(u!=v) {
					if(dep[u]<dep[v])swap(u,v);
					cnt[u]++;
					if(cnt[u]==1)l[u]=x,r[u]=y;
					else f[u]=fa[u];
					u=find(fa[u]);
				}
			} else {
				scanf("%d",&x);
				if(!cnt[x])printf("Not yet\n");
				else if(cnt[x]==1)printf("%d %d\n",l[x],r[x]);
				else if(cnt[x]>1)printf("Many times\n");
			}
		}
	}
}

上一题