当前位置: 首页 > >

# ICPC2021昆明重现赛_K.Parallel Sort

发布时间:

Parallel Sort

题目链接在此!!


题面:


中文题意:

对于每个数,其所在位置向最终位置连边,会形成很多环。
合并环的操作只能让轮数增加,可以认为环与环之间的操作互不影响。
因此对每一个环单独考虑如何通过最少轮数的操作将其消除。


对于每个环:


    如果元素==2,那么交换1次即可。如果元素>2,那么交换2次即可。

因为是一个环,如果进行题意中的交换,会发现换过一次后只要再换一次就可以有序。
所以最多只要进行两轮交换。


代码:

#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1145140;
vector> ans[maxn];
bool vis[maxn] = {0};
int a[maxn];

int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++) {
if (vis[i])continue;
int tmpp = i;
vector tmp;
while (!vis[tmpp]) {
vis[tmpp] = 1;
tmp.push_back(tmpp);
tmpp = a[tmpp];
}
if (tmp.size() == 1)continue;
else if (tmp.size() == 2) {
ans[1].push_back({tmp[0], tmp[1]});
} else {
for (int l = 1, r = tmp.size() - 1; l < r; l++, r--) {
if( l >= r) break;
ans[1].push_back({tmp[l], tmp[r]});
int tmppp=tmp[l];
tmp[l]=tmp[r];
tmp[r]=tmppp;
// swap(tmp[l], tmp[r]);
}
for (int l = 0, r = tmp.size() - 1;; l++, r--) {
if( l >= r) break;

ans[2].push_back({tmp[l], tmp[r]});
}
}
}
int sn = 0;
for (int i = 1; i <= 2; i++) {
if (ans[i].size()) {
sn++;
}
}
cout << sn << endl;
for (int i = 1; i <= sn; i++) {
cout << ans[i].size() <<" ";
for (auto k:ans[i]) {
cout << k.first << << k.second<<" " ;
}
}
}



友情链接: