逆序对

定义

设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。

如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。

实现

归并排序

在归并排序中,利用cnt计数即可。

void mergeArray(int arr[],int first,int mid,int last) 
{
    int i=first,j=mid+1,m=mid,n=last,k=0,temp[maxn];
    while(i<=m&&j<=n)
    {
      if(arr[i]<=arr[j]) temp[k++]=arr[i++];
      else temp[k++]=arr[j++],cnt+=m-i+1;
    }
    while(i<=m) temp[k++]=arr[i++];
    while(j<=n) temp[k++]=arr[j++];
    for(i=0;i<k;i++) arr[first+i]=temp[i];
}
void mySort(int arr[],int first,int last) 
{
  if(first<last)
  {
    int mid=(first+last)/2;
    mySort(arr,first,mid);
    mySort(arr,mid+1,last);
    mergeArray(arr,first,mid,last);
  }
}

树状数组

线段树也不是不行。-O-O-

P1908 逆序对

#include<bits/stdc++.h>
using namespace std;
const int maxn=500100;
struct node
{
  int w,id;
  node(){}
  node(int a,int b){id=a;w=b;}
  bool operator<(const node &n) const
  {
    if(w!=n.w) return w>n.w;
    else return id>n.id;
  }
}w[maxn];
int tree[maxn],n;
int lowbit(int x);
int check(int x);
void update(int x);
int main()
{
  int i,x;
  long long ans=0;;
  scanf("%d",&n);
  for(i=1;i<=n;i++) 
  {
    scanf("%d",&x);
    w[i]=node(i,x);
  }
  sort(w+1,w+1+n);
  for(i=1;i<=n;i++)
  {
    ans+=check(w[i].id);
    update(w[i].id);
  }
  printf("%lld\n",ans);
  return 0;
}
int lowbit(int x)
{return x&(-x);}
int check(int x)
{
  int ans=0;
  for(;x>0;x-=lowbit(x)) ans+=tree[x];
  return ans;
}
void update(int x)
{
  for(;x<=n;x+=lowbit(x)) tree[x]++;
}
posted @ 2019-09-06 23:40  Vivid-BinGo  阅读(194)  评论(0编辑  收藏  举报