当前位置: 代码迷 >> 综合 >> (2021 ICPC)亚洲区域赛(昆明)J.Parallel Sort(思维)
  详细解决方案

(2021 ICPC)亚洲区域赛(昆明)J.Parallel Sort(思维)

热度:70   发布时间:2023-12-21 00:00:33.0

题目链接:https://ac.nowcoder.com/acm/contest/12548/J

分析

数字所要去的位置会形成一个循环关系,如 2 3 4 1 ,会形成如下的循环关系:
2 要到 3 的位置,3 要到 4 的位置 4 要到 1 的位置:
在这里插入图片描述
我们如果将其进行对称交换,会发现下一轮只要再换一次就可以有序。
所以最多只要进行两轮交换。

代码
#include<bits/stdc++.h>
using namespace std;int n,cnt;
int a[100005];
vector<int> ans[3],tmp;
map<int,int> vis;int main()
{
    int flag = 1;cin>>n;for(int i=1;i<=n;i++){
    cin>>a[i];if(a[i] != i) flag = 0;}if(flag == 1){
    cout<<"0\n";return 0;}cnt++;vis.clear();for(int i=1;i<=n;i++){
    if(vis[i] == 1) continue;if(i != a[i]){
    if(a[a[i]] == i){
    int to = a[i];if(vis[to] == 1) continue;vis[i] = vis[to] = 1;ans[cnt].push_back(i);ans[cnt].push_back(to);swap(a[i],a[to]);}else{
    tmp.clear();int tt = 0;for(int to=a[i];vis[to]!=1;to=a[to]){
    vis[to] = 1;tmp.push_back(to);}for(int j=0,k=tmp.size()-1;j<k;j++,k--){
    ans[cnt].push_back(tmp[j]);ans[cnt].push_back(tmp[k]);swap(a[tmp[j]], a[tmp[k]]);}}}}flag = 1;for(int i=1;i<=n;i++) if(a[i] != i){
    flag = 0;break;}if(flag == 1){
    cout<<"1\n"<<(ans[1].size() / 2)<<" ";for(int i=0;i<ans[1].size();i++) cout<<ans[1][i]<<" ";cout<<"\n";return 0;}cnt++;for(int i=1;i<=n;i++){
    if(i == a[i]) continue;int to = a[i];ans[cnt].push_back(i);ans[cnt].push_back(to);swap(a[i], a[to]);}cout<<"2\n";cout<<(ans[1].size() / 2)<<" ";for(int i=0;i<ans[1].size();i++) cout<<ans[1][i]<<" ";cout<<"\n";cout<<(ans[2].size() / 2)<<" ";for(int i=0;i<ans[2].size();i++) cout<<ans[2][i]<<" ";cout<<"\n";//cout<<"ans: ";//for(int i=1;i<=n;i++) cout<<a[i]<<" ";return 0;
}
  相关解决方案