归并排序及应用

void merge_sort(int *s,int l,int h,int *t)  //t辅助数组
{
    if(h-l>1){
        int mid = l+(h-l)/2;
        int i=l,p=l,q=mid;
        merge_sort(s,l,mid,t);
        merge_sort(s,mid,h,t);
        while(p<mid||q<h){
            if(q>=h||(p<mid&&s[p]<=s[q])) t[i++]=s[p++];
            else t[i++]=s[q++];
        }
    }
    for(int i=l;i<h;i++)    s[i]=t[i];
}

int main()
{
    int s[10]={10,3,5,2,1,4,8,6,9,7},t[10]={10,3,5,2,1,4,8,6,9,7};
    for(int i=0;i<10;i++)   printf(i==9?"%d
":"%d ",s[i]);
    merge_sort(s,0,10,t);
    for(int i=0;i<10;i++)   printf(i==9?"%d
":"%d ",s[i]);
    return 0;
}

逆序对问题,给出一个序列,求逆序对数,及有多少个又需对(i,j)是的i<j但ai>aj。n高达10e6

可以种归并排序求解,或者也可以用树状数组。

int c;
void merge_sort(int *s,int l,int h,int *t)  //t辅助数组
{
    if(h-l>1){
        int mid = l+(h-l)/2;
        int i=l,p=l,q=mid;
        merge_sort(s,l,mid,t);
        merge_sort(s,mid,h,t);
        while(p<mid||q<h){
            if(q>=h||(p<mid&&s[p]<=s[q])) t[i++]=s[p++];
            else t[i++]=s[q++],c+=mid-p;
        }
    }
    for(int i=l;i<h;i++)    s[i]=t[i];
}

int main()
{
    int s[10]={6,7,8,9,10,1,2,3,4,5},t[10]={6,7,8,9,10,1,2,3,4,5};
    for(int i=0;i<10;i++)   printf(i==9?"%d
":"%d ",s[i]);
    merge_sort(s,0,10,t);
    for(int i=0;i<10;i++)   printf(i==9?"%d
":"%d ",s[i]);
    printf("%d
",c);
    return 0;
}

应用:

考分鄙视(exam)

时间限制: 1 Sec  内存限制: 64 MB
提交: 15  解决: 5
[提交][状态][讨论版]

题目描述

  Whence这个学期考了n次试,每一次都有一个0~20000之间的整数分数。Whence本来的状态应该是每一次考试都比前一次多一分(除第一次), 但由于他很不稳定,偏差可能很大。对于第i次考试,如果有第j次考试满足l≤j<i≤n,且以第j次考试分数作为基准估计的第i次考试成绩比实际成 绩低,就说第i次考试鄙视了第j次考试(估计分可以超过20000)。为了提高自信,Whence想知道他这个学期所有考试总共有多少次鄙视。

输入

第1行n (l<n≤100000);
第2行为n次考试成绩。

输出

1行,这个学期所有考试的总共鄙视次数(总数可能很大,只需要输出总数mod 12345的值)。

样例输入

4
1 3 3 5

样例输出

3

提示

样例说明:第一次考试的分数是1,那么估计应该是第二次为2,第三次为3,第四次为4, 但第二次实际分数为3,比2大,这是1次鄙视;第四次实际分数为5,比估计的4大,这也是1次鄙视;第二次考试的分数是3,那么估计应该是第三次为4,第 四次为5,实际分数分别是3和5,所以没有鄙视;第三次考试的分数为3,那么估计第四次是4,但实际为5,这又是1次鄙视。因此总鄙视次数为3次。

分析:当i-j<s[i]-s[j]受到鄙视,即s[j]-j<s[i]-i受到鄙视。 把数组倒置。 即求逆序对。。

#include <cstring>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <queue>
#define fi first
#define se second
#define pi pair<int,int>
#define md make_pair
#define ha pair<int,pair<int,pi> >
using namespace std;
const int inf=0x3f3f3f3f;
int c,s[100010],t[100010];
void merge_sort(int *s,int l,int h,int *t)  //t辅助数组
{
    if(h-l>1){
        int mid = l+(h-l)/2;
        int i=l,p=l,q=mid;
        merge_sort(s,l,mid,t);
        merge_sort(s,mid,h,t);
        while(p<mid||q<h){
            if(q>=h||(p<mid&&s[p]<=s[q])) t[i++]=s[p++];
            else t[i++]=s[q++],c=(c+mid-p)%12345;
        }
    }
    for(int i=l;i<h;i++)    s[i]=t[i];
}

int main()
{
    //freopen("data.in","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",s+i),s[i]-=i,t[i]=s[i];
    reverse(s+1,s+n+1);
    reverse(t+1,t+n+1);
    //for(int i=1;i<=n;i++)printf("%d ",s[i]);printf("
");
    merge_sort(s,1,n+1,t);
    //for(int i=1;i<=n;i++)printf("%d ",s[i]);printf("
");
    printf("%d
",c);
    return 0;
}
原文地址:https://www.cnblogs.com/acmtime/p/5727394.html