AtCoder Regular Contest 136 B 题解

AtCoder Regular Contest 136 B

  • 有关逆序对的讨论

    • 对于不存在相同数字的逆序对,进行题意操作并不会改变逆序对奇偶性

    以 1 3 5 举例

    进行题意操作后所有可能的序列为

    • 1 3 5(逆序对数量为0)

    • 5 1 3(逆序对数量为2)

    • 3 5 1(逆序对数量为2)

    • 对于存在相同数字的逆序对,进行题意操作可能会改变逆序对奇偶性

    以 1 1 4 举例

    进行题意操作后所有可能的序列为

    • 1 1 4(逆序对数量为0)

    • 4 1 1(逆序对数量为2)

    • 1 4 1(逆序对数量为1)

  • 对于每个数字出现次数相同的序列a,b,我们总是可以通过题意变化使得前n-2个数相同(对于一个特定的数,只要他大于等于n-2,我们就可以通过变换使他上移1位或者2位,经过若干次变换一次可以到达任意位置(第n-1和n位除外))

    a1 a2 … an-2 ai aj

    b1 b2 … bn-2 bi bj

  • 如果不存在相同数字,ai肯定等于bi,aj肯定等于bj,不然逆序对数奇偶性就改变了

  • 如果存在相同数字,假设有两个5

    我们一定可以通过变换使得序列变为

    a1 a2 … 5 5 ai aj

    b1 b2 … 5 5 bi bj

    • 由上述关于奇偶性的讨论可以知道ai不一定等于bi,但是我们一定可以通过变换使得ai和aj交换位置(第一次以aj为z,变为5 aj 5 ai;第二次以第二个5为z,变为5 5 aj ai)
  • 总体思路

    • 判断所有数字出现个数相不相同,如果不相同一定不可以
    • 判断是否有两个或者两个以上相同的数,有的话一定可以
    • 判断逆序对数奇偶性是不是相同,相同可以,不相同不可以
  • AC代码

#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstring>
#include <list>
#include <numeric>

#define int long long
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
int a[maxn];
int b[maxn];


signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int n;
    map<int, int> ma;
    map<int, int> mb;
    while (cin >> n) {
        for (int i = 0; i < n; ++i) {
            int x;
            cin >> x;
            a[i] = x;
            ma[x]++;
        }
        for (int i = 0; i < n; ++i) {
            int x;
            cin >> x;
            b[i] = x;
            mb[x]++;
        }
        int an = 0, bn = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = i; j < n; ++j) {
                if (a[i] > a[j]) an++;
                if (b[i] > b[j]) bn++;
            }
        }
        int symbol = 0;
        for (auto mm: ma) {
            if (mm.second >= 2) symbol = 1;
            if (ma[mm.first] != mb[mm.first]) {
                cout << "No" << '\n';
                return 0;
            }
        }
        if (symbol==1) {cout<<"Yes"<<'\n';return 0;}
        if (an % 2 == bn % 2) cout << "Yes" << '\n';
        else cout << "No" << '\n';
        

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值