紫书第八章-----高效算法设计(归并排序求逆序对数)

Brainman POJ - 1804

【代码一(暴力)】


#include

using namespace std;

const int maxn=1000+5;

int a[maxn],t[maxn];
long long cnt;
int T,N,kase=0;

void solve(){
    cnt=0;
    for(int i=0;ifor(int j=i+1;jif(a[i]>a[j]) cnt++;
        }
    }
}


int main()
{
    cin>>T;
    while(T--){
        cin>>N;
        for(int i=0;icin>>a[i];
        solve();
        cout<<"Scenario #"<<++kase<<":"<return 0;
}

【代码二(归并排序求逆序对数)】

/*
    该程序参考刘汝佳《算法竞赛入门经典》(第2版)
    本代码是用归并排序来统计逆序对数。
    首先归并排序的分治法的三步走战略:划分问题+递归求解+合并问题
    其次,归并排序统计逆序对数目的原理是这样子的:首先我们得明确
    一个事实,比如6 1 7 2这四个数,6 1这两个数放一块,7 2两个数放
    一块,这两个部分内部不论怎么交换,并不影响由于其他块的数产生
    的逆序对数目,现在以6 1 7 2为例,我们以7 2这一块来说,归并排序
    中当7进入临时空间的时候,看看6 1这一块还剩下几个元素没有入临时
    空间,剩下的元素必定比7大,剩下的元素个数就是由于7产生的逆序对
    数目,同样地1产生的逆序对数目类似统计,同样,由于不同块之间互不
    影响,递归解决此问题。说的有点乱,但仔细想想是这个道理!!!!!
*/

#include

using namespace std;

const int maxn=1000+5;

int a[maxn],t[maxn];
int cnt;

//归并排序求解逆序对数目,左闭右开区间
void merge_sort(int a[],int x,int y,int t[]){
    if(y-x>1){  //递归结束条件
        int mid=x+(y-x)/2;  //分治第一步:划分问题,尽量等分为两份
        int p=x,q=mid,i=x;
        merge_sort(a,x,mid,t);//分治第二步:递归左边求解
        merge_sort(a,mid,y,t);//分治第二步:递归右边求解
        while(pif(q>=y || (p//复制给临时辅助数组空间
            else{
                t[i++]=a[q++];  //复制给临时辅助数组空间
                cnt=cnt+mid-p;  //统计逆序对数目
            }
        }
        for(i=x;i//分治第三步:合并问题
    }
}


int main()
{
    int T,N,kase=0;
    cin>>T;
    while(T--){
        cin>>N;
        for(int i=0;icin>>a[i];
        cnt=0;
        merge_sort(a,0,N,t);
        cout<<"Scenario #"<<++kase<<":"<return 0;
}

你可能感兴趣的:(紫书第八章-----高效算法设计(归并排序求逆序对数))