CF1592B Hemose Shopping 题解

luogu传送门

题意简述:

\(t\) 组数据。

每组数据给定一个数 \(x\) 以及一个长度为 \(n\) 的数列 \(a_1,a_2,…,a_n\)

当 \(|j-i|>=x(1\le i,j\le n)\) 时,你可以交换 \(a_i,a_j\)。

问你能否将这个序列变为从小到大的。

\(\texttt{SOLUTION}\)

当 \(2\times x\le n\) 时,答案一定是 YES

因为我们可以通过 \(a_1,a_n\) 当中转或直接交换排列中的任意两个数字。

我来举个例子:

如果 \(n=6,x=3\)

\(a={1\ 6\ 3\ 5\ 2\ 4}\)

  • 目标:交换 \(3\ 2\)
  • 操作:
    • 交换 \(3\ 4\)
    • 交换 \(2\ 1\)
    • 交换 \(2\ 3\)
    • 交换 \(2\ 4\)
    • 交换 \(3\ 1\)
  • 目标:交换 \(6\ 4\)
  • 操作:
    • 交换 \(6\ 4\)

当 \(2\times x\geq n\) 时,我们只能通过上述相同方法任意交换 \(a_1,a_2,…,a_{n-x}\) 和 \(a_{x+1},a_{n-x+2},…,a_n\)。

而 \(a_{n-x+1},a_{n-x+1},…,a_{x}\) 无法移动。

设将 \(a\) 从小到大排序后为 \(s\)。

所以如果答案为 YES, \(a_{n-x+1},a_{n-x+1},…,a_{x}\) 一定与 \(s_{n-x+1},s_{n-x+1},…,s_{x}\)相同。

否则答案就为 NO

\(\texttt{AC CODE}\)

#include<bits/stdc++.h>
using namespace std;
const int MAX=100010;
int read()
{
	int x=0; char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
int n,x,a[MAX],s[MAX];
bool check(int l,int r)
{
	for(int i=1;i<=n;i++) s[i]=a[i];
	sort(s+1,s+n+1);
	for(int i=l;i<=r;i++) if(a[i]!=s[i]) return 0;
	return 1;
}
int main()
{
	int t=read();
	while(t--)
	{
		n=read(),x=read();
		for(int i=1;i<=n;i++) a[i]=read();
		if(2*x<=n) puts("YES");
		else puts(check(n-x+1,x)?"YES":"NO");
	}
	return 0;
}
上一篇:循环卷积(离散化)


下一篇:【HAOI2018】染色