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;
}