内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述SORT公司是一个专门提供排序服务的公司,该公司的宗旨是:“顺序是美丽的”。他们的工作是通过一系列移动,将某些物品按顺序摆好。他们的服务是通过工作量来计算的,即移动物品的次数。所以,在工作前必须先考察工作量,以便向客户提出收费数目。
用户并不需要知道精确的移动次数,实质上,大多数人都是凭感觉来认定这一列物品的混乱程度。根据SORT公司的经验,人们一般是根据“逆序对”的数目多少来称呼这一序列的混乱程度。假设将序列中第I件物品的参数定义为Ai,那么排序就是将A1,……An从小到大排序。若i
SORT公司请你写一个程序,在尽量短的时间内统计出”逆序对“的数目。
输入格式
第1行为n(1<=n<=100000)
接下来N行,每行一个长整数型范围内的整数。
输出格式
一个整数,为逆序对的数目。
样例输入
5
3
1
4
5
2
样例输出
4
1.逆序对:设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。
2.本题目用归并算法,在每层递归中累加逆序对的数量
#includeusing namespace std; const int N=1e6+10; int a[N],tmp[N]; int merge_sort(int a[],int l,int r){ if(l>=r)return 0; int mid=l+r>>1; int ret=merge_sort(a,l,mid)+merge_sort(a,mid+1,r); int x=l,y=mid+1,k=0; while(x<=mid&&y<=r) if(a[x]<=a[y])tmp[k++]=a[x++]; else { tmp[k++]=a[y++];ret+=mid+1-x; } while(x<=mid)tmp[k++]=a[x++]; while(y<=r)tmp[k++]=a[y++]; for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j]; return ret; } int main(){ int n;cin>>n; for(int i=0;i >a[i]; cout< 但是数据大小有点问题,改成long long ,龙龙这样就过了
#includeusing namespace std; typedef long long ll; const int N=1e6+10; int a[N],tmp[N]; ll merge_sort(int a[],int l,int r){ if(l>=r)return 0; int mid=l+r>>1; ll ret=merge_sort(a,l,mid)+merge_sort(a,mid+1,r); int x=l,y=mid+1,k=0; while(x<=mid&&y<=r) if(a[x]<=a[y])tmp[k++]=a[x++]; else { tmp[k++]=a[y++];ret+=mid+1-x; } while(x<=mid)tmp[k++]=a[x++]; while(y<=r)tmp[k++]=a[y++]; for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j]; return ret; } int main(){ int n;cin>>n; for(int i=0;i >a[i]; cout< 总结: 归并算法来源于acwing,算法模板如下:
#includeusing namespace std; typedef long long ll;//long long比较长写起来比较麻烦,故用typedef ll merge_sort(int l, int r);//该函数的功能为直接返回逆序对个数 const int N = 1e5 + 10; int q[N], n, a[N]; int main() { cin >> n; for (int i = 0; i > q[i]; cout << merge_sort(0, n - 1) < if (l == r) return 0;//递归的终点 int mid = l + r >> 1; ll count = merge_sort(l, mid) + merge_sort(mid + 1, r);//将左右逆序对数量先加总 int i = l, j = mid + 1, k = 0; while(i<=mid && j<=r) { if (q[i]<=q[j]) a[k++] = q[i++]; else { count = count + (mid + 1 - i);//由上图可知此处右侧每个数能与左侧构成的逆序对有mid + 1 -i个 a[k++] = q[j++]; } } while(i<=mid) a[k++] = q[i++];//扫尾 while(j<=r) a[k++] = q[j++];//扫尾 for (i = l, k = 0; i<=r;) q[i++] = a[k++];//归还数组元素 return count;//返回逆序对个数 }//该代码引用AcWing网站的代码



