资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
老虎moreD是一个勤于思考的青年,线性代数行列式时,其定义中提到了逆序数这一概念。不过众所周知我们只需要知道逆序数的奇偶性就行了,为了防止计算上的失误,moreD准备编写一个小程序来判定。只要判断奇偶性就行了哦!
另外作为一个技术宅,moreD对线性代数中最小下标为1非常不满,于是所有下标均从0开始。
输入格式
一个测试点包含多组数据,你需要不断读入直到输入结束。
每组数据第一行为一个n,接下来第二行输入n个数字,是一个0到n-1的排列。
输出格式
输出若干行,每行表示对应组数据逆序数奇偶性,奇数输出odd,偶数输出even。
样例输入
5
0 1 2 3 4
5
4 3 1 2 0
样例输出
even
odd
数据规模和约定
设每组测试点T个数据
1<=T<=10
1<=n<=100000
首先看暴力方法,超时(仅供理解题意):
4 3 1 2 0,求逆序数的方法:
- 对于第1个数字4,前面没有比它大的数,逆序数为0
- 对于3,前面有比它大的数字4,逆序数为1
- 对于1,前面有4,3,都比它大,逆序数为2
- 对于2 ,前面有4,3,1,两个比它大,逆序数为2
- 对于0,前面有4,3,1,2,都比它大,逆序数为4
因此,该序列的逆序数=0+1+2+2+4=9,为odd
cpp
#include<iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
int a[n];
for(int i=0;i<n;i++){
cin>>a[i];
}
long long int sum=0;
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(a[j]>a[i]) sum++;
}
}
if(sum%2==0) cout<<"even"<<endl;
else cout<<"odd"<<endl;
}
return 0;
}
归并算法
cpp
#include<iostream>
using namespace std;
const int N=100005;
int a[N];//待排序的数组
int tmp[N];
int res=0;
void msort(int l,int r){
if(l==r) return;//只有一个数
int mid=(l+r)>>1;
msort(l,mid);
msort(mid+1,r);
//合并
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r){
if(a[i]<=a[j]) tmp[k++]=a[i++];
else{
tmp[k++]=a[j++];
res+=mid-i+1;
}
}
while(i<=mid) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(int i=l;i<=r;i++) a[i]=tmp[i];
}
int main(){
int n;
while(cin>>n){
res=0;
for(int i=0;i<n;i++){
cin>>a[i];
}
msort(0,n-1);
if(res%2==0) cout<<"even"<<endl;
else cout<<"odd"<<endl;
}
return 0;
}
思路:归并算法。在右段取数时,计算逆序数,即取右段中的数时,该数的逆序数为左段中比它大的数。