toj1455 Ultra-QuickSort

来源:互联网 发布:淘宝好评率低于97 编辑:程序博客网 时间:2024/06/16 03:42

题目链接:http://acm.tju.edu.cn/toj/showp.php?pid=1455

题目大意:给定一个序列,要有多少次邻近元素的交换才能使其成升序排列

思路:转换为求逆序数  这里引入求逆序数的一种模板方法:归并排序求逆序数

代码:

//归并排序 求逆序数
#include<iostream>
using namespace std;
int num[500010];
int t[500010];
long long cnt; //注意要开大点,否则过不了

 

归并排序模板

void merge_sort(int *a,int left,int right,int *b){  //归并模板 先要排好左右,再合并
    int mid,l,r,k,i;
    if(right>left){
       mid=(left+right)/2;
       merge_sort(a,left,mid,b);//归并左数组
       merge_sort(a,mid+1,right,b); //归并右数组
       l=left,r=mid+1,k=left;
       while(l<=mid && r<=right){
           if(a[l]<=a[r]){
              b[k++]=a[l++];
           }else{
              b[k++]=a[r++];
              cnt+=(mid+1)-l; //记录有多少逆序对,因为在右数组的r处,在左数组中有mid-l个数比r大(因为左右部分都是已经排好序的)
                              //cnt这句去掉就是归并排序的模板
           }
       }
       while(l<=mid){
           b[k++]=a[l++];
       }
       while(r<=right){
           b[k++]=a[r++];
       }
       for(i=left;i<=right;i++){
           a[i]=b[i];
       }
    } 
}

int main()
{
    int n,i;
    while(cin>>n && n){
       cnt=0;
       for(i=0;i<n;i++)
       cin>>num[i];
       merge_sort(num,0,n-1,t);//参数 原数组 左边界 右边界(不是长度) 归并后的数组
       cout<<cnt<<endl;
    }
    return 0;
}

 

原创粉丝点击