题目链接:~~~
题目大意:
给 n 个数,每个数有一个权值 ai。有一个操作:每次可以交换两个相邻的数。
问:是否可以对每个数都进行偶数次操作,使得这个数升序。
分析:
第一点:一个数 ax 到它排序后的位置 y 需要的操作次数是一定的:| x - y | ,(ps:多换了没用,故意换到另一边,还需要再换回来
第二点:如果 x 和 y 同样是偶数或者奇数,| x - y | 的结果为偶数
第三点:根据一二,我们只需要判断一下是不是奇偶对应即可
第四点:对 x 和 y 模 2,这时 0 就是偶数 1 就是奇数,用 pair 存对应信息。把原数组排序前的信息存到 A中,再把原数组排序后的信息存到 B 中。对 A 和 B 排序,看对应位置的就是否相同即可。
ps:解释一下第四点最后排序的意义,在 A 和 B 中,0 表示偶数 1 表示奇数,对 A 和 B排序,就可以保证偶数在前,奇数在后。如果0对0,1对1,就表示满足操作次数为偶数,否则操作次数是奇数。
eg:
比如 A 中存储信息为:(15, 0),(15, 1), (15, 0),说明有三个 15 ,三个15中,两个在的偶数位,一个在奇数位
对 A 排序后变为:(15, 0) , (15, 0), (15, 1)。
这时,对原数组排序后,B 中存储的信息若为:(15, 1),(15, 0), (15, 0),说明排序后有三个 15 ,三个15中,两个在的偶数位,一个在奇数位
对 B 排序后为:(15, 0) , (15, 0), (15, 1)
A 和 B,相同,说明全部都是偶数次操作
若:B中的信息为:(15, 1),(15, 1), (15, 0),说明排序后有三个 15 ,三个15中,一个在的偶数位,两个在奇数位
对 B 排序后为:(15, 0) , (15, 1), (15, 1)
A 和 B,不相同,说明必须有一个15需要奇数次操作才能到达对应的位置
参考代码:
#include <vector>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#define ll long long
#define chushi(a, b) memset(a, b, sizeof(a))
#define endl "\n"
const double eps = 1e-8;
const ll INF=0x3f3f3f3f;
const int mod=1e9 + 7;
const int maxn = 5e5 + 5;
using namespace std;
int a[maxn];
vector<pair<int, int> > x;
vector<pair<int, int> > y;
int main(){
int ncase;
cin >> ncase;
while(ncase--){
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) x.push_back({a[i], i % 2});
sort(a+1, a+1+n);
for(int i = 1; i <= n; i++) y.push_back({a[i], i % 2});
sort(x.begin(), x.end());
sort(y.begin(), y.end());
if(x == y) cout << "YES" << endl;
else cout << "NO" << endl;
x.clear();
y.clear();
}
return 0;
}