zoukankan      html  css  js  c++  java
  • 逆序对

    逆序对

    逆序对:满足i<j且a[i]>a[j]的所有的(a[i],a[j])对的个数。

     

    I.正常的方法O(n^2):

    可以从i或j的角度出发

    Code:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define maxn 10000
     4  
     5 int main()
     6 {
     7     long a[maxn+1],n,ans,i,j;
     8     scanf("%ld",&n);
     9     for (i=1;i<=n;i++)
    10         scanf("%ld",&a[i]);
    11     ans=0;
    12     //i<j
    13     for (i=1;i<n;i++)
    14         for (j=i+1;j<=n;j++)
    15             //a[i]>a[j]
    16             if (a[i]>a[j])
    17                 ans++;
    18     printf("%ld
    ",ans);
    19     ans=0;
    20     //i>j
    21     for (i=n;i>1;i--)
    22         for (j=i-1;j>=1;j--)
    23             //a[i]<a[j]
    24             if (a[i]<a[j])
    25                 ans++;
    26     printf("%ld
    ",ans);
    27     return 0;
    28 }
    29 /*
    30 10
    31 5 3 2 10 1 6 9 4 8 7
    32 4+2+1+6+0+1+3+0+1+0=18
    33 3+2+4+1+1+4+0+2+1+0=18
    34 */

     

     

    II.有两种方法求逆序对使得时间复杂度为O(nlogn):

    1.归并排序+统计

    2.离散化+树状数组

     

    1.归并排序+统计

     1 Code:
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #define maxn 100000
     5  
     6 ///mergesort:O(nlogn)
     7  
     8 long a[maxn+1],t[maxn+1];
     9 //max_ans:maxn*(maxn-1)/2=4999950000 , use long long
    10 long long ans=0;
    11  
    12  
    13 void mergesort(long l,long r)
    14 {
    15     if (l==r)
    16         return ;
    17     long mid,x,y,z,i;
    18     mid=(l+r)/2;
    19     mergesort(l,mid);
    20     mergesort(mid+1,r);
    21     for (i=l;i<=r;i++)
    22         t[i]=a[i];
    23     x=l;
    24     y=mid+1;
    25     z=l;
    26     while (x<=mid && y<=r)
    27     {
    28         //两个数相等时让左边的数先加,因为相同的数不能凑成一对
    29         if (t[x]<=t[y])
    30         {
    31             a[z]=t[x];
    32             x++;
    33             //a[x] > a[mid+1]~a[y-1]
    34             ans+=(y-mid-1);
    35         }
    36         else if (t[x]>t[y])
    37         {
    38             a[z]=t[y];
    39             y++;
    40         }
    41         z++;
    42     }
    43     if (x<=mid)
    44     {
    45         //a[x] > a[mid+1]~a[r]
    46         ans+=(mid-x+1)*(r-mid);
    47         while (z<=r)
    48         {
    49             a[z]=t[x];
    50             x++;
    51             z++;
    52         }
    53     }
    54     else
    55     {
    56         while (z<=r)
    57         {
    58             a[z]=t[y];
    59             y++;
    60             z++;
    61         }
    62     }
    63 }
    64  
    65 int main()
    66 {
    67     long n,i;
    68     scanf("%ld",&n);
    69     for (i=1;i<=n;i++)
    70         scanf("%ld",&a[i]);
    71     mergesort(1,n);
    72     printf("%lld
    ",ans);
    73     return 0;
    74 }
    75 /*
    76 Input:
    77 10
    78 5 3 2 10 1 6 9 4 8 7
    79 Output:
    80 18
    81 */

     

    2.离散化+树状数组

    Code:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #define maxn 10000
     4  
     5 //离散化(数为1~n;或数很集中除外)+树状数组(求a[k+1]~a[n]中小于a[k]的数)
     6  
     7 struct node
     8 {
     9     long value,pos;
    10 }s[maxn+1];
    11 //n个数,最多有n个不同的数值
    12 long a[maxn+1],c[maxn+1];
    13  
    14 int cmp(const void *a,const void *b)
    15 {
    16     if ((*(struct node *)a).value<(*(struct node *)b).value)
    17         return -1;
    18     else
    19         return 1;
    20 }
    21  
    22 int main()
    23 {
    24     long n,i,t,v;
    25     long long ans;
    26     scanf("%ld",&n);
    27     for (i=1;i<=n;i++)
    28     {
    29         scanf("%ld",&s[i].value);
    30         s[i].pos=i;
    31     }
    32     //排序
    33     qsort(s+1,n,sizeof(struct node),cmp);
    34     //离散化(保留数的大小关系;数值无所谓,舍弃之)
    35     //设置最小值为2,是为了之后比(a[i]-1)小的数
    36     t=1;
    37     for (i=1;i<=n;i++)
    38     {
    39         t++;
    40         a[s[i].pos]=t;
    41         while (i<n && s[i].value==s[i+1].value)
    42         {
    43             i++;
    44             a[s[i].pos]=t;
    45         }
    46     }
    47     //树状数组
    48     for (i=1;i<=t;i++)
    49         c[i]=0;
    50     ans=0;
    51     for (i=n;i>=1;i--)
    52     {
    53         //获得小于等于(a[i]-1),即小于a[i]的数
    54         v=a[i]-1;
    55         while (v>0)
    56         {
    57             ans+=c[v];
    58             v=v-(v & (-v));
    59         }
    60         //添加a[i]
    61         v=a[i];
    62         while (v<=t)
    63         {
    64             c[v]++;
    65             v=v+(v & (-v));
    66         }
    67     }
    68     printf("%lld
    ",ans);
    69     return 0;
    70 }
    71 /*
    72 Input:
    73 10
    74 5 3 2 10 1 6 9 4 8 7
    75 Output:
    76 18
    77 */
    78  
  • 相关阅读:
    Python-cookie,session
    Django_models下划线__正反查询,对象正反查询
    Python利用PIL生成随机验证码图片
    简单实用的分页类-python
    Django_Form验证(三)字段,字段的参数,widgets种类
    Django_Form验证(二),ajax验证
    Django_Form验证(一)
    Django提交文件的方式
    在linux下安装python3.6.6
    celery学习
  • 原文地址:https://www.cnblogs.com/cmyg/p/6905989.html
Copyright © 2011-2022 走看看