Gym 100971B Derangement

要求改换序列,使得没有位置是a[i] == i成立。输出最小要换的步数

首先把a[i] == i的位置记录起来,然后两两互相换就可以了。

对于是奇数的情况,和它前一个换或者后一个换就可以,(注意前一个越界或者后一个越界)

这样是不会重复的,因为本来i是a[i] == i的话,换了一个,是不会使得他们两个a[i] == i的

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 200000 + 20;
int a[maxn];
vector<int>pos;
void work ()
{
    int n;
    cin>>n;
    for (int i = 1; i <= n; ++i) scanf ("%d",&a[i]);
    for (int i = 1; i <= n; ++i) {
        if (a[i] == i)
            pos.push_back(i);
    }
    printf ("%d\n",pos.size() / 2 + (pos.size() & 1));
    if (pos.size() & 1) {
        for (int i = 0; i < pos.size() - 1; i += 2) {
            printf ("%d %d\n",pos[i],pos[i + 1]);
        }
        int t1 = pos[pos.size() - 1] - 1;
        int t2 = pos[pos.size() - 1] + 1;
        int ans;
        if (t1 != 0) {
            ans = t1;
        } else {
            ans = t2;
        }
        printf ("%d %d\n",pos[pos.size() - 1],ans);
    } else {
        for (int i = 0; i < pos.size(); i += 2) {
            printf ("%d %d\n",pos[i],pos[i + 1]);
        }
    }
    return ;
}
int main()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work ();
    return 0;
}
View Code

 

posted on 2016-08-28 19:42  stupid_one  阅读(192)  评论(0编辑  收藏  举报

导航