1. 程式人生 > 其它 >【題解】CF1585D Yet Another Sorting Problem

【題解】CF1585D Yet Another Sorting Problem

題意

給定一個長度為 \(n\) 的陣列 \(a\)
每次操作可以選擇三個數進行迴圈右移。
詢問是否可以將陣列排序。

Sol

若陣列中存在相同的數,那麼顯然有解。
再考慮沒有數相同的情況。
由於是挑 \(3\) 個數迴圈右移,那麼每次逆序對的數量會減少 \(2\)
那麼統計一下逆序對即可。
我用的是樹狀陣列。時間複雜度 \(O(n \log n)\),存在 \(O(n)\) 做法。

Code

//LYC_music yyds!
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0)
#define lowbit(x) (x&(-x))
using namespace std;
inline char gc()
{
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
int read()
{
	int pos=1,num=0;
	char ch=getchar();
	while (!isdigit(ch))
	{
		if (ch=='-') pos=-1;
		ch=getchar();
	}
	while (isdigit(ch))
	{
		num=num*10+(int)(ch-'0');
		ch=getchar();
	}
	return pos*num;
}
void write(int x)
{
	if (x<0)
	{
		putchar('-');
		write(-x);
		return;
	}
	if (x>=10) write(x/10);
	putchar(x%10+'0');
}
void writesp(int x)
{
	write(x);
	putchar(' ');
}
void writeln(int x)
{
	write(x);
	putchar('\n');
}
const int N=5e5+10;
bool vis[N],flag;
int n,a[N],tree[N];
inline void add(int x,int y)
{
	for (;x<=n;x+=lowbit(x))
		tree[x]+=y;
}
inline int query(int x)
{
	int res=0;
	for (;x;x-=lowbit(x))
		res+=tree[x];
	return res;
}
signed main()
{
	int T=read();
	while (T--)
	{
		n=read(); flag=0;
		for (int i=1;i<=n;i++)
			vis[i]=0,tree[i]=0;
		for (int i=1;i<=n;i++)
		{
			a[i]=read();
			if (vis[a[i]]) flag=1;
			vis[a[i]]=1;
		}
		if (flag)
		{
			puts("YES");
			continue;
		}
		int res=0;
		for (int i=1;i<=n;i++)
		{
			res+=query(n)-query(a[i]);
			add(a[i],1);
		}
		if (res&1) puts("NO");
		else puts("YES");
	}
}