D. Yet Another Sorting Problem
题意
给你一个数组,每次你可以选择一个三元组 ( i , j , k ) (i,j,k) (i,j,k)然后将 a i , a j , a k a_i,a_j,a_k ai,aj,ak 循环移动依次,问你是否可以通过若干次操作将该数组变成非递减的。
思路
- 思维
首先假设三个位置是 1 , 2 , 3 1,2,3 1,2,3,可以发现你将第一个数放到某个地方之后 后续的移动就已经固定了(因为要形成要给三元环),因此可能的结果只有 2 , 3 , 1 2,3,1 2,3,1和 3 , 1 , 2 3,1,2 3,1,2两种。
如何判断是否合法?最简单的方式就是模拟一遍,从左向右一个一个复原,但是你发现 搞成 2 , 3 , 1 2,3,1 2,3,1更优,还是 3 , 1 , 2 3,1,2 3,1,2更优是不确定的。因此再观察一下性质,发现这两种方式都只会让逆序对 + 2 / − 2 +2/-2 +2/−2也就是你操作一次对总逆序对的奇偶性不产生改变,所以启迪我们直接从逆序对入手,直接判断是否可行。
然后我们刚才的考虑情况是默认三个数均不同的,发现如果三个数里存在一样的,逆序对就可能产生奇数变化,这样的话一定有解了。
因此特判是否有相同的,然后统计一下逆序对,判断奇偶性即可。
Code
#include <bits/stdc++.h>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 5e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N];
bool st[N];
int tr[N];
void add(int x) {
for (; x <= n; x += x & -x) tr[x] ++;
}
int sum(int x) {
int res = 0;
for (; x; x -= x & -x) res += tr[x];
return res;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int T;
cin >> T;
while (T -- ) {
cin >> n;
for (int i = 1; i <= n; i ++) st[i] = false, tr[i] = 0;
bool ok = false;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
if (st[a[i]]) ok = true;
st[a[i]] = true;
}
if (ok) {
cout << "YES\n";
continue ;
}
LL s = 0;
for (int i = n; i; i --) {
s += sum(a[i]);
add(a[i]);
}
if (s & 1) cout << "NO\n";
else cout << "YES\n";
}
return 0;
}
博客围绕数组排序问题展开,给定数组,可选择三元组循环移动元素,判断能否使数组非递减。思路是先分析三元组移动结果,发现操作对逆序对奇偶性的影响,再考虑数相同的情况,通过特判相同数和统计逆序对奇偶性来判断是否可行。
1314

被折叠的 条评论
为什么被折叠?



