• Evanyou Blog 彩带


      首先我们得理解一下什么是逆序对。在一个数列$a$中,满足$a[i]>a[j]$并且$i<j$的数对就叫做逆序对。

      一般求逆序对常用的有两种方法,归并排序和树状数组。(我个人比较喜欢归排)这两样不会的请出门左转百度。

      下面就讲讲这两种方法:

      首先讲讲归排求逆序对。归并排序用到了二分的思想,在排序过程中如果$a[i]<=a[j]$就不会产生逆序对,如果$a[i]>a[j]$就会产生$mid-i+1$个逆序对,因为做归排的时候$l~mid$和$mid+1~r$都是已经排好序的所以如果$a[i]>a[j]$那么$a[i+1]~a[mid]$也就都大于$a[j]$,这个非常容易懂,下面是代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=40005;
    int n,a[N],c[N],ans;
    void ready()
    {
      cin>>n;
      for(int i=1;i<=n;i++)
        cin>>a[i];
    }
    inline void msort(int l,int r)
    {
      if(l==r)return;
      int mid=(l+r)>>1;
      msort(l,mid);msort(mid+1,r);
      int i=l,j=mid+1,k=l;
      while(i<=mid&&j<=r){
        if(a[i]<=a[j])
          c[k++]=a[i++];
        else{
          c[k++]=a[j++];
          ans+=(mid-i+1);
        }
      }
      while(i<=mid)c[k++]=a[i++];
      while(j<=r)c[k++]=a[j++];
      for(i=l;i<=r;i++)
        a[i]=c[i];
    }
    void work()
    {
      msort(1,n);
      cout<<ans<<endl;
    }
    int main()
    {
      std::ios::sync_with_stdio(false);
      ready();work();return 0;
    }

      再来讲讲树状数组,这个可能比归排的要不那么容易理解。使用树状数组求逆序对还需要进行离散化操作(因为数据过大的话无法直接开数组),对于离散后的序列进行一次遍历,遍历过程中就向树状数组C进行插入操作(每次插入的值为1),这里树状数组表示的是在该元素前面但是比该元素大的元素个数,进行插入操作以后就查询。。。我觉得看代码貌似会容易理解一点。。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=40005;
    int n,b[N],c[N],ans;
    struct node{int v,id;}a[N];
    inline int lowbit(int x)
    {return x&(-x);}
    inline void insert(int i,int x)
    {
      while(i<=n){
        c[i]+=x;i+=lowbit(i);
      }
    }
    inline int getnum(int x)
    {
      int ret=0,i=x;
      while(i>0){
        ret+=c[i];i-=lowbit(i);
      }
      return ret;
    }
    inline bool cmp(node x,node y)
    {return x.v<y.v;}
    void work()
    {
      cin>>n;
      for(int i=1;i<=n;i++){
        cin>>a[i].v;
        a[i].id=i;
      }
      sort(a+1,a+n+1,cmp);
      for(int i=1;i<=n;i++)b[a[i].id]=i;
      for(int i=1;i<=n;i++){
        insert(b[i],1);
        ans+=i-getnum(b[i]);
      }
      cout<<ans<<endl;
    }
    int main()
    {
      std::ios::sync_with_stdio(false);
      work();return 0;
    }

      

  • 相关阅读:
    MySQL 学习(六) InnoDB事务及MVCC
    MySQL学习(二) 存储过程
    一个二级缓存实例 (多级缓存)
    MySQL 学习(五) InnoDB架构
    验证POST接口是否可跨域(自用小工具,自用测试页面)
    用WindowsAppSDK(WASDK)优雅的开发上位机应用
    用PC windows作为Mac macos的扩展屏
    第一次使用webpack
    前端代码压缩工具closesure compiler
    JS代码操作CSS样式文件
  • 原文地址:https://www.cnblogs.com/cytus/p/7811856.html
Copyright © 2020-2023  润新知