拿个沙发
此题是典型的思维题,且 “思维容易,实现难” 主要是实现比较难想到。
代码如下,具体细节通过注释给出
其中,c 数组记录选中数在 a 中的下标,d 数组记录选中数的值,c 和 d 的配合可以对选出来的离散集合进行排序,通过排序后的结果,依次修改 a 数组和 b 数组。
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
int a[100009], b[100009], n;
int c[100009], d[100009], vis[100009];
void fu(int l, int r){
int tot = 0; memset(vis, 0, sizeof(vis));
/// 确保前四分之一的数在集合中
for(int i = l; i <= r; i ++){
if(!vis[i]) c[++ tot] = i, vis[i] ++;
if(!vis[b[i]]) c[++ tot] = b[i], vis[b[i]] ++;
}
/// 如果不够二分之一的数, 则补足缺少的部分
for(int i = r + 1; tot < n / 2; i ++)
if(!vis[i]) c[++ tot] = i;
/// 打印答案
for(int i = 1; i <= n / 2; i ++) {
if(i != 1) cout << ' ';
cout << c[i];
} cout << endl;
/// 利用 c 、d 数组对保存临时值,对离散的集合排序
for(int i = 1; i <= tot; i ++)
d[i] = a[c[i]];
sort(c + 1, c + n / 2 + 1);
sort(d + 1, d + 1 + tot);
for(int i = 1; i <= n / 2; i ++)
a[c[i]] = d[i];
/// 重置修改后的 b 数组
for(int i = 1; i <= n; i ++)
b[a[i]] = i;
}
int main(){
cin >> n;
for(int i = 1; i <= n;i ++) {
cin >> a[i];
b[a[i]] = i;
}
cout << 3 << endl; /// 三步必定可以成功,先排前四分之一,再排第二个四分之一,最后排最后二分之一
fu(1, n / 4);
fu(n / 4 + 1, n / 2);
for(int i = n / 2 + 1; i <= n; i ++) {
if(i != n / 2 + 1) cout << ' ';
cout << i;
}
return 0;
}
最后欢迎大家给我指出值得改进的地方。

京公网安备 11010502036488号