zoukankan      html  css  js  c++  java
  • 归并排序及应用

    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;
    }
  • 相关阅读:
    Android Button四种点击事件和长按事件
    Android 简单登陆 涉及 Button CheckBox TextView EditText简单应用
    Android EditText属性
    Android-TextView 控件常用属性以及基本用法
    对象数组空指针异常
    数字反转问题
    遇3问题
    队列解密QQ号
    线程先后执行问题
    小哼买书
  • 原文地址:https://www.cnblogs.com/acmtime/p/5727394.html
Copyright © 2011-2022 走看看