Codeforces-1681 C: Double Sort 【排序】

Codeforces-1681 C: Double Sort

题目传送门:Codeforces-1681 C

题目

题目截图

在这里插入图片描述

样例描述

在这里插入图片描述

题目大意

  给定两个长度为 n n n 的数组 a 、 b a、b ab。可以执行的操作为选择两个下标 i , j i,j i,j,同时交换 a i 、 a j a_i、a_j aiaj b i 、 b j b_i、b_j bibj,问能否将两个数组都排成不降序列。

题目解析

  首先题目给的范围是 1 0 4 10^4 104 次交换,然而,我们的数组长度最多也就 100 100 100,这意味着我们可以把两两都交换一遍,因此这个交换范围我们可以忽略,最后直接找出排序顺序即可。
  之后的问题是如何排序,首先,如果我们知道偏序的概念,我们可以直接定义一个偏序关系为 a i ≤ a j a_i \le a_j aiaj b i ≤ b j b_i \le b_j bibj,如果能够排序成功,那么就说明我们可以用题目所说的交换排序。然而,用这种偏序有时候是不可比的,因为没有完全性。但我们可以用另一种方法去代替它,使得它变成全序关系,即先以 a i ≤ a j a_i \le a_j aiaj 排序,再以 b i ≤ b j b_i \le b_j bibj 排序,加入先后顺序之后,我们可以直接对两个数组进行排序。显然,如果能够排序后两个数组都有序,那么我们就得到了最终的数组。
  之后我们用排序算法,将排好序的数组与原数组进行比较,从小到大,我们逐个交换元素,让原数组变成排好序的数组,就可以得到交换序列了。

Code

#include <bits/stdc++.h>
using namespace std;

int main() {
    int t, n;
    cin >> t;
    while(t--) {
        cin >> n;
        vector<pair<int, int>> vec(n, make_pair(0, 0));
        for(int i=0; i<n; ++i)
            cin >> vec[i].first;
        for(int i=0; i<n; ++i)
            cin >> vec[i].second;
        vector<pair<int, int>> p(vec);
        sort(vec.begin(), vec.end());
        bool fl = false;
        for(int i=1; i<n; ++i) {
            if(vec[i].second < vec[i-1].second) {
                cout << -1 << endl;
                fl = true;
                break;
            }
        }
        if(!fl) {
            vector<pair<int, int>> ans;
            for(int i=0; i<n; ++i) {
                if(vec[i].first != p[i].first || vec[i].second != p[i].second) {
                    for(int j=i+1; j<n; ++j) {
                        if(vec[i].first == p[j].first && vec[i].second == p[j].second) {
                            ans.push_back(make_pair(i+1, j+1));
                            swap(p[i], p[j]);
                            break;
                        }
                    }
                }
            }
            cout << ans.size() << endl;
            for(int i=0; i<ans.size(); ++i)
                cout << ans[i].first << " " << ans[i].second << endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值