题意
给你一个长度为 \(N\) 的序列 \(X\) ,其中每个元素都介于 \(1\) 和 \(N\) 之间(含),以及一个长度为 \(N\) 的序列 \(A\) 。
打印在 \(A\) 上执行以下操作 \(K\) 次的结果。
将 \(A_i\) 替换为\(A_{X_i}\)。每个操作同时进行。
思路
元素 \(i\) 经过 \(k\) 次变化后的值就是元素 \(X_i\) 经过 \(k-1\) 次变化后的值。
于是我们可以将 \(i\) 和 \(X_i\) 连边。很容易发现,每一个点的出度为 \(1\),这是一颗内向基环树。于是我们处理每一个点到环上的距离,如果距离比 \(k\) 小,那么直接倍增爬树,否则直接在树上转圈圈。
Code
// Problem: E - Permute K times
// Contest: AtCoder - AtCoder Beginner Contest 367
// URL: https://atcoder.jp/contests/abc367/tasks/abc367_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
namespace gtx{
// Fast IO
void read(int &x){
x = 0;int h = 1;char tmp;
do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
x*=h;
}
void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
void write(char x){putchar(x);}
void write(int x){
if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
do{st[++tot]=x%10,x/=10;} while(x);
while(tot){putchar(st[tot--]+'0');};
}
void write(int x,char y){write(x);write(y);}
const int MAXN = 2e5+10;
const int LOGN = log2(MAXN)+10;
int n,k;
//DSU
int fath[MAXN];
int get_father(int x){
if(x==fath[x]) return x;
return fath[x] = get_father(fath[x]);
}
//Topo
int rd[MAXN],nxt[MAXN],ordinary[MAXN],root[MAXN];
bitset<MAXN> loop;
void Topo(){
loop.set();
queue<int> q;
for(int i = 1;i<=n;i++){
if(rd[i]==0) q.push(i);
}
while(!q.empty()){
int k = q.front();q.pop();
loop.reset(k);
if(--rd[nxt[k]]==0) q.push(nxt[k]);
}
}
//ST
int ST_fath[MAXN][LOGN],dis[MAXN],is[MAXN];
int jump(int x,int tmp){
int k = 0;
while(tmp){
if(tmp&1) x = ST_fath[x][k];
tmp>>=1;
k++;
}
return x;
}
void ST_init(){
for(int j = 1;j<LOGN;j++){
for(int i = 1;i<=n;i++){
ST_fath[i][j] = ST_fath[ST_fath[i][j-1]][j-1];
}
}
}
//Base ring tree
int find_loop(int k,int &r){
if(dis[k]) return r=root[k],dis[k];
if(loop[k]) return r=k,dis[k]=0;
ST_fath[k][0] = nxt[k];
return dis[k] = find_loop(nxt[k],root[k])+1,r=root[k],dis[k];
}
vector<int> has[MAXN];
bitset<MAXN> vis;
void dfs(int k){
if(vis[k]) return;
vis[k] = 1;
is[k] = has[get_father(k)].size();
has[get_father(k)].push_back(k);
dfs(nxt[k]);
}
signed main(){
read(n);read(k);
for(int i = 1;i<=n;i++) fath[i] = i;
for(int i = 1;i<=n;i++){
read(nxt[i]);
fath[get_father(i)] = get_father(nxt[i]);
rd[nxt[i]]++;
}
for(int i = 1;i<=n;i++){
read(ordinary[i]);
}
Topo();
for(int i = 1;i<=n;i++){
find_loop(i,root[i]);
}
for(int i = 1;i<=n;i++){
if(loop[i]){
dfs(i);
}
}
ST_init();
for(int i = 1;i<=n;i++){
if(k<dis[i]) write(ordinary[jump(i,k)],' ');
else write(ordinary[has[get_father(root[i])][(is[root[i]]+(k-dis[i]))%has[get_father(root[i])].size()]],' ');
}
return 0;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T = 1;
// gtx::read(T);
while(T--) gtx::main();
return 0;
}
Tag
Atcoder
、ABC
基环树