列表

详情


NC233870. 【模板】Prufer 序列

描述

请实现 Prufer 序列和无根树的相互转化。

为方便你实现代码,尽管是无根树,我们在读入时仍将 n 设为其根。

对于一棵无根树,设 为其父亲序列f_i 表示 in 为根时的父亲),设 为其 Prufer 序列

另外,对于一个长度为 m 的序列 ,我们设其权值

输入描述

第一行两个整数 ,表示树的点数和转化类型。

,第二行一行 n-1 个整数,表示父亲序列。
,第二行一行 n-2 个整数,表示 Prufer 序列。

输出描述

,一行一个整数,表示给出的父亲序列对应的 Prufer 序列的权值。 
,一行一个整数,表示给出的 Prufer 序列对应的父亲序列的权值。

示例1

输入:

6 1
3 6 4 6 1

输出:

29

示例2

输入:

6 2
4 6 5 2

输出:

4

原站题解

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

C++ 解法, 执行用时: 91ms, 内存消耗: 5240K, 提交时间: 2022-04-25 10:08:54

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define int ll
#define ll long long
const int maxn=5e6+5;
int cnt;
int a[maxn],ans[maxn],in[maxn];
int n,c; 
signed main(){
	cin>>n>>c;
	if(c==1){
		for(int i=1;i<=n-1;i++)cin>>a[i],in[a[i]]++;
		int minn;
		for(int i=1;i<=n-1;i++)
		if(!in[i]){
			minn=i;break;
		}
		int now=minn;
		while(cnt<n-2){
			ans[++cnt]=a[now];
			in[a[now]]--;
			if(!in[a[now]]&&a[now]<minn)now=a[now];
			else{
				minn++;
				while(in[minn])minn++;
				now=minn;
			}
		}
		int res=0;
		for(int i=1;i<=n-2;i++)
		res^=(i*ans[i]);
		cout<<res;
	}else{
		for(int i=1;i<=n-2;i++)cin>>a[i],in[a[i]]++;
		a[n-1]=n;in[n]++;
		int minn;
		for(int i=1;i<=n-1;i++)
		if(!in[i]){
			minn=i;break;
		}
		int now=minn;
		for(int i=1;i<=n-1;i++){
			ans[now]=a[i];
			in[a[i]]--;
			if(!in[a[i]]&&a[i]<minn)now=a[i];
			else{
				minn++;
				while(in[minn])minn++;
				now=minn;
			}
		}
		int res=0;
		for(int i=1;i<=n-1;i++)
		res^=(i*ans[i]);
		cout<<res;
	} 
     return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 42ms, 内存消耗: 2784K, 提交时间: 2022-08-19 20:35:38

#include<bits/stdc++.h>
using namespace std ;
const int N = 5e6 + 5 ;
#define ll long long
int n,m ;
int f[N],d[N],p[N] ;
ll ans=0 ;
void TP()
{
	for(int i=1;i<n;++i) scanf("%d",&f[i]),d[f[i]]++ ;
	for(int i=1,j=1;i<=n-2;++i,++j)
	{
		while(d[j]) ++j ; p[i]=f[j] ;
		while(i<=n-2&&!--d[p[i]]&&p[i]<j) p[i+1]=f[p[i]],++i ;
	}
	for(int i=1;i<=n-2;++i) ans^=1ll*i*p[i] ;
}
void PT()
{
	for(int i=1;i<=n-2;++i) scanf("%d",&p[i]),++d[p[i]] ;
	p[n-1]=n ;
	for(int i=1,j=1;i<n;++i,++j)
	{
		while(d[j]) ++j ; f[j]=p[i] ;
		while(i<n&&!--d[p[i]]&&p[i]<j) f[p[i]]=p[i+1],++i ;
	}
	for(int i=1;i<n;++i) ans^=1ll*i*f[i] ;
}
int main()
{
	scanf("%d%d",&n,&m) ;
	if(m==1) TP() ;
	else PT() ;
	printf("%lld\n",ans) ;
	return 0 ;
}

上一题