ABC E抽象做法求条
查看原帖
ABC E抽象做法求条
894358
binomial楼主2024/8/19 08:59

RT.十分抽象。大致做法是找环,对每个环算出环内元素位置,对于环外边对其指向的环依次取值。

下面是代码。(别再回复倍增了!)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,x[800005],y[800005],a[800005],flag[800005],flag2[800005],ss[800005],start,len,fa[800005],ans[800005],wz[800005];
vector<int>hl[800005];
long long k;
void dfs(int now){
	if(flag2[now]){
		start=wz[now]+1;
		int siz=hl[len].size();
		int ls=k%siz;
		for(int j=start-1;j<siz;j++){
			ans[hl[len][j]]=a[hl[len][((j+ls))%siz]];//找环

		}
		return ;
	}
	flag2[now]=1;
	flag[now]=1;
	hl[len].push_back(now);
	ss[now]=len;
	wz[now]=hl[len].size()-1;
	if(!flag[x[now]]||flag2[x[now]]){
		dfs(x[now]);
		flag2[now]=0;
	}
	else{
		int siz=hl[len].size(),siz2=hl[ss[x[now]]].size();
		for(int i=siz-1;i>=0;i--){//顺次继承
			ans[hl[len][i]]=ans[hl[ss[x[now]]][((wz[x[now]]-(siz-i))%siz2+siz2)%siz2]];
			flag2[hl[len][i]]=0;
		}
		return ;
	}
	if(wz[now]==start-1){//顺次继承
		int siz=wz[now],siz2=hl[ss[x[now]]].size()-wz[now];
		for(int i=siz-1;i>=0;i--){
			ans[hl[len][i]]=ans[hl[ss[x[now]]][start-1+((wz[x[now]]-(siz-i))%siz2+siz2)%siz2]];
			flag2[hl[len][i]]=0;
		}
		return ;
	}
	return ;
}
signed main(){
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%lld",&x[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<=n;i++){
		if(!flag[i]){
			start=i;
			len++;
			dfs(i);
		}
	}
	for(int i=1;i<=n;i++){
		printf("%lld ",ans[i]);
	}
    return 0;
}
2024/8/19 08:59
加载中...