题解:AT_abc367_e [ABC367E] Permute K times
题意
给你一个长度为 的序列 ,其中每个元素都介于 和 之间(含),以及一个长度为 的序列 。
打印在 上执行以下操作 次的结果。
将 替换为。每个操作同时进行。
思路
元素 经过 次变化后的值就是元素 经过 次变化后的值。
于是我们可以将 和 连边。很容易发现,每一个点的出度为 ,这是一颗内向基环树。于是我们处理每一个点到环上的距离,如果距离比 小,那么直接倍增爬树,否则直接在树上转圈圈。
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
基环树
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】