给定一个 1∼n的排列 a1,a2,…,an。
我们规定,交换操作指从排列中随机选择两个不同元素并交换彼此位置。
给定两种打乱排列的方式:
- 对排列连续进行 3n次交换操作。
- 对排列连续进行 7n+1次交换操作。
已知,给定排列 a1∼an就是由 1,2,…,n经过上述两种打乱方式之一得到的。
请你判断,给定排列具体是由哪一种打乱方式得到的。
输入格式
第一行包含整数 n。
第二行包含 n个整数 a1,a2,…,an
。
输出格式
如果给定排列是由方式 1
打乱得到的,则输出 1
,如果给定排列是由方式 2
打乱得到的,则输出 2
。
保证给定排列一定是由两种打乱方式之一得到的。
数据范围
前 3 个测试点满足 2≤n≤10。
所有测试点满足 2≤n≤106,保证 a1∼an是一个 1∼n的排列。
输入样例:
5
2 4 5 1 3
输出样例:
1
解析
本道题考察的就是逆序对的模型,因此我们可以用归并排序的模板来做,一下是代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1000010;
int n;
int w[N],b[N];
int res;
void merge(int l,int r){
if(l==r)return ;
int x=(l+r)>>1;
merge(l,x);
merge(x+1,r);
int i=l,j=x+1,k=l;
while(i<=x&&j<=r){
if(w[i]<=w[j])b[k++]=w[i++];
else b[k++]=w[j++],res+=(x-i+1)%2;
}
while(i<=x)b[k++]=w[i++];
while(j<=r)b[k++]=w[j++];
for(int i=l;i<=r;i++){
w[i]=b[i];
}
res%=2;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>w[i];
}
merge(1,n);
if(res==3*n%2)cout<<1;
else cout<<2;
return 0;
}
题目来源 acwing