Parallel Sort
题面:
中文题意:
对于每个数,其所在位置向最终位置连边,会形成很多环。
合并环的操作只能让轮数增加,可以认为环与环之间的操作互不影响。
因此对每一个环单独考虑如何通过最少轮数的操作将其消除。
对于每个环:
- 如果元素==2,那么交换1次即可。
- 如果元素>2,那么交换2次即可。
因为是一个环,如果进行题意中的交换,会发现换过一次后只要再换一次就可以有序。
所以最多只要进行两轮交换。
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 1145140;
vector<pair<int, int>> 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<int> 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<<" " ;
}
}
}