C. Omkar and Baseball(思维)

思路:思维题,结论:最多不超过两次操作。

1 : 1: 1:已经排好了, 0 0 0次操作。

2 : 2: 2:只有一段连续区间都不在自己的位置, 1 1 1次操作。

3 : 3: 3:其他两次操作。

这里着重解释下 3 3 3。

其实我们只需两次的对整个数组进行操作即可。

第一次操作目的是将一半较大的数放在后面,然后将一半较小的数放在前面。

最后再对整个数组排个序即可,这样显然在第二次操作时就能满足前面较小的数移动位置到后面,后面的较大的数移动位置到前面,保证操作的可行性。

当 n n n为偶数时。

e p : 126453 ep:126453 ep:126453。

显然我们可以将后面3个数变为 546 546 546,前面 3 3 3个数变为 312 312 312。然后再操作一次就行了。

当 n n n为奇数时同理。

e p : 53124 ep:53124 ep:53124,先变为 54123 54123 54123,然后再操作一次即可。

可能有人还是会问为什么这样就是可行的呢?

事实上 n ≤ 4 n\leq 4 n≤4显然操作不超过两次。

对于 n > 4 n>4 n>4时,显然对于前一半和后一半都不止一种排列方式,我们只需任意构造一种将大的数放在前面的一种,将小的数放在后面的一种,然后再操作一次即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int f=0,cnt=0;
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
if(x!=i&&!f) f=1,cnt++;
else if(x==i) f=0;
}
if(!cnt) puts("0");
else if(cnt==1) puts("1");
else puts("2");
}
return 0;
}