ARC102D Revenge of BBuBBBlesort!
Link
首先发现一次操作相当于交换两个距离为\(1\)的数。
那么如果奇数位上有偶数或者偶数位上有奇数,一定就是不合法的。
注意到对原排列进行一次操作,会让逆序对数减少\(3\)。
我们把奇数位和偶数位分成两个排列,那么对原排列进行一次操作,会让这两个排列中的某个排列的逆序对数减少\(1\)。
因此第二个必要条件是原排列的逆序对数为奇数偶数位分开后的两个排列的逆序对数之和的\(3\)倍。
然后我们证明这也是充分条件。
考虑对分开后的两个排列冒泡排序,每次这两个排列中的某一个逆序对数会减少\(3\)。
而对于原排列,逆序对数会减少不超过\(3\)。并且如果逆序对数减少了\(3\),那么这一定是一个合法的操作。
由第二个条件可知每次操作都是合法的,因此如果满足了第一个条件,那么这个排列就是合法的。
#include<cstdio>
#include<vector>
#include<cstring>
using i64=long long;
int n,flg=1,t[300007];std::vector<int>p[3];
int read(){int x;scanf("%d",&x);return x;}
void add(int p){while(p)++t[p],p^=p&-p;}
int ask(int p){int r=0;while(p<=n)r+=t[p],p+=p&-p;return r;}
i64 tao(std::vector<int>p){i64 r=0;memset(t,0,sizeof t);for(int x:p)r+=ask(x),add(x);return r;}
int main()
{
n=read();
for(int i=1,x;i<=n;++i) p[2].push_back(x=read()),p[i&1].push_back(x),flg&=!((i^x)&1);
puts(flg&(tao(p[2])==3*(tao(p[0])+tao(p[1])))? "Yes":"No");
}