zoukankan      html  css  js  c++  java
  • 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;
    }

      

  • 相关阅读:
    SQLite 基本使用
    SQLite 语法
    html5晋级之路-css介绍
    html5晋级之路-web storage
    html5晋级之路-元素语法
    html晋级之路-背景、实体
    ios-晋级之路 CocoaPods的使用
    如何在Mac OS X上安装 Ruby运行环境
    html5晋级之路-学习笔记表单
    html5晋级之路-学习笔记
  • 原文地址:https://www.cnblogs.com/cytus/p/7811856.html
Copyright © 2011-2022 走看看