Petya有一个整数数组a1 a2, an-他只喜欢排序数组。不幸的是,给定的数组可能是任意的,所以Petya想对它进行排序。Petya喜欢挑战自己,所以他想只用3个循环来排序数组。更正式地说,在一个操作中,他可以选择3个成对不同的指标i, j和k(1≤i, j, k≤n),并对数组a应用i→j→k→icycle。它同时将a放在位置j上,aj放在位置k上,ak放在位置i上,而不改变任何其他元素。例如,如果a是[10,50,20,30,40,60],他选择i = 2, j = 1, k = 5,那么数组就变成[50,40,20,30,10,60]。Petya可以应用任意数量的3-cycle(可能是0)。你要确定彼佳是否能对他的数组a排序,即使它是非递减的。输入每个测试包含多个测试用例。第一行包含测试用例的数量t (1 < t < 5 - 105)。测试用例的描述如下。每个测试用例的第一行包含一个整数n (1 <n <5- 105)——数组a的长度。每个测试用例的第二行包含n个整数a1, a2,…, an(1≤ai≤n)。它保证所有测试用例的n的和不超过5 - 105。输出对于每个测试用例,如果Petya可以使用3个循环对数组a排序,则打印“YES”(不带引号),否则打印“NO”(不带引号)。您可以在任何情况下打印每个字母(大写或小写)。
Example
input
Copy
7 1 1 2 2 2 2 2 1 3 1 2 3 3 2 1 3 3 3 1 2 4 2 1 4 3
output
Copy
YES YES NO YES NO YES YES
题解:
在写本道题前,我们应该清楚一些定义
定义:降序次数为偶数的排列为偶排列;降序次数为奇数的排列为奇排列。
例如排列(2,3,1):从左往右看,2与其后元素相比有降序,即2大于1;3与其后元素相比有降序,即3大于1;1无降序;则排列降序次数为2次,因此为偶排列。
例如排列(1,3,2):从左往右看,1与其元素无降序,3与其后元素有降序,2无降序;因此其排列降序次数为1,为奇排列。
假设原位置1 , 2 , 3
按题目规则排完只有两种形式,
2 3 1 (逆序对数为 2)
3 1 2 (逆序对数为 2)
按照题目中所给规则,一次改变会将会将逆序对的数量变化2,所以我们只需要利用树状数组,看逆序对数目是否为偶数即可
还有一种特殊情况是,假如有两个数相等的情况,一定是可以的
我们刚才的考虑情况是默认三个数均不同的,发现如果三个数里存在一样的,逆序对就可能产生奇数变化,这样的话一定有解了。
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
int a[500050];
int f[500050];
int tre[500050];
int lowbit(int x)
{
return x & - x;
}
int sum(int x)
{
int res = 0;
for(int i = x;i ;i -= lowbit(i))
res += tre[i];
return res;
}
void add(int x,int n)
{
for(int i = x;i <= n;i += lowbit(i))
tre[i] ++;
}
void solve()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
f[i] = 0,tre[i] = 0;
int ff = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
if(f[a[i]])
{
ff = 1;
}
f[a[i]]++;
}
if(ff)
{
printf("YES\n");
return ;
}
int res = 0;
for(int i = 1;i <= n;i++)
{
res += sum(n) - sum(a[i]);
add(a[i],n);
}
if(res&1)
{
printf("NO\n");
}
else
{
printf("YES\n");
}
}
//1 2 4
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
scanf("%d",&t);
while (t--)
{
solve();
}
return 0;
}
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//0 1 1 1 1
//0 1 1 1 1