• 求逆序对


    给定一个序列a1,a2,…,an,如果存在iaj,那么我们称之为逆序对,求逆序对的数目 

    Input

    第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。 
    N<=10^5。Ai<=10^5

    Output

    两行,第一行为所有逆序对总数,第二行为本质不同的逆序对总数。 

    Sample Input

    4 
    3 
    2 
    3 
    2 

    Sample Output

    3
    1

    sol:利用归并排序的思想求逆序对。

    归并排序的核心思想是分治,当我们将a数组里的数分得足够小的时候,开始逐一合并过程,合并时,分别用指针i,j指向两边的头(即i=l, j=mid+1),分别往后扫,每次取出两个指针所指的数中较小的放入b数组。如果取出的是左边的数放入b数组,则左右两边的数不构成逆序对,如果是右边的数放入b数组,这时a[i]>a[j],说明i~mid间的所有数都比a[j]大(因为左边有序,右边有序),此时,逆序对数增加mid-i+1个。

     1 #include <cstdio>
     2 int a[30010],b[30010];
     3 int ans=0;
     4 int n;
     5 void merge(int s,int t)
     6 //s是左边界,t是右边界 
     7 {
     8     if(s==t)return;
     9     int mid=s+t>>1;
    10     merge(s,mid); //左边排好 
    11     merge(mid+1,t);//右边排好 
    12     int i=s,j=mid+1;
    13     int p=s-1;//记一个位置 
    14     while(i<=mid&&j<=t) //但没有过界的时候 
    15     {
    16         if(a[i]<=a[j]) //将a[i]放入b数组 
    17         {
    18             b[++p]=a[i];
    19             i++;
    20         }
    21         else
    22         {
    23             b[++p]=a[j];//将a[j]放入b数组 
    24             j++;
    25             ans+=mid+1-i;//逆序对增加mid+1-i个 
    26         }
    27     }
    28     while(j<=t)//把a[j]剩下的全部放入b数组 
    29     {
    30         b[++p]=a[j];
    31         j++;
    32     }
    33     while(i<=mid)//把a[i]剩下的全部放入b数组 
    34     {
    35         b[++p]=a[i];
    36         i++;
    37     }
    38     for(int i=s;i<=t;i++) 
    39     a[i]=b[i];
    40 }
    41 int main()
    42 {
    43     scanf("%d",&n);
    44     for(int i=1;i<=n;i++)
    45     scanf("%d",&a[i]);
    46     merge(1,n);
    47     printf("%d",ans);
    48 }
    
    
  • 相关阅读:
    mvc 在ii7上发布时遇到的问题只解决
    @Html.Raw 显示Html的标签
    补发————grid布局
    补发————DOM与BOM
    web实验博客3.css-position
    web专业课学习及往后方向发展
    bom&dom
    网格代码
    简单用户注册表单
    自我介绍
  • 原文地址:https://www.cnblogs.com/cutepota/p/12129232.html
Copyright © 2020-2023  润新知