CSL 的魔法(牛客竞赛)

CSL 的魔法(牛客竞赛)_第1张图片
CSL 的魔法(牛客竞赛)_第2张图片
题目链接
参考代码

  • 题目思路:这个题目明显就是要排序的,第一个序列最小值和第二个序列最大值相对应,以此类推。(但是只知道应该是这样,但代码实现……还得看大佬代码)只能说自己还是太菜了,读大佬的代码还读了一会,然后做了下注释,做下笔记。
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];

struct pot
{
    int id; //记录该数字在原序列中的位置
    int val;
    bool operator < (const pot &obj) const
    {
        return val < obj.val;
    }
}p[maxn], p1[maxn];

int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++) scanf("%d", &p[i].val), p[i].id = i;
    for(int i = 1; i <= n; i++) scanf("%d", &p1[i].val), p1[i].id = i;
    sort(p+1, p+1+n);
    sort(p1+1, p1+1+n);
    for(int i = 1; i <= n; i++)
        a[p1[n-i+1].id] = p[i].id;  //记录第二排数据的位置对应元素应该与第一排数原据结合的位置
    int ans = 0;    //ans用来记录不需要操作的个数
    for(int i=1;i<=n;i++)   //如果原来第一排与第二排的数据本来就应该结合,那么就不用交换
        if(a[i] == i)   ans++;
    for(int i = 1; i <= n; i++)
    {
        if(a[i] == i)   continue ;  //如果刚刚已经记录过,那么直接跳过
        ans++;
        //如果这个原本不对应,那么就需要交换位置,但是一定交换到最后,
        //两个点交换一次之后位置相对应,这样在遍历下一个点的时候直接就跳过了,默认是交换了一次,所以多了一次,在这里记录一下,减去多着的这一次
        //比如,有n个数的位置两两不对应(一定注意,这里处理的一定是两两不对应,如果对应好就直接跳出了),那么这n个数字你只需要交换n-1次,
        //但是你在遇到其中第一个数的时候,就将位置全部对应好了,然后
        //遍历到后面的点的时候,就会直接跳过,每一个点都直接跳过,也就是剩下的n-1个数都是默认需要交换一次才能找到自己对应的位置,如果这里不记录ans++
        //那么,这n个数就相当于交换了n次,有一次是多余的。emmm,如果还不明白,可以自己写两个两两不对应的序列,自己试一下,就明白了
        int xx = a[i];
        //接下来,将两两不对应的数字都复位
        while(a[xx] != xx)
            swap(a[xx], xx);
    }
    cout << n-ans << endl;
    return 0;
}

你可能感兴趣的:(基础算法)