題意
給你一個長度為 \(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
基環樹