P1908 逆序对

P1908 逆序对

题目简述

求数列中逆序对个数


思路:

方法一:

利用树状数组,倒着来做(类似思想同P1168 中位数

方法二:

利用归并排序,每次排序后可以利用其单调性性质直接算出答案(详细参考这个


代码

方法一:

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=5e5+5;
int a[N],b[N];
ll c[N];
int n;
int lowbit(int x){
  return x&(-x);
}
void add(int x,int y){
  for(int i=x;i<=n;i+=lowbit(i))c[i]+=y;
}
ll query(int x){
  ll ans=0;
  for(int i=x;i;i-=lowbit(i))ans+=c[i];
  return ans;
}
int main(){
  cin>>n;
  for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i];
  sort(a+1,a+1+n);
  int tot=unique(a+1,a+1+n)-a-1;
  for(int i=1;i<=n;i++)b[i]=lower_bound(a+1,a+1+tot,b[i])-a;
  ll ans=0;
  for(int i=n;i>=1;i--){
    add(b[i],1);
    ans+=query(b[i]-1);
  }
  cout<<ans<<endl;
  return 0;
}

方法二:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+5;
int a[N],c[N];
ll ans;
int n;
void msort(int l,int r){
  if(l==r)return ;
  int mid=(l+r)>>1;
  msort(l,mid);
  msort(mid+1,r);
  int b1=l,b2=mid+1;
  int tmp=l;
  while(b1<=mid&&b2<=r){
    if(a[b1]>a[b2]){
      ans+=mid-b1+1;
      c[tmp++]=a[b2];
      b2++;
    }
    else {
      c[tmp++]=a[b1];
      b1++;
    }
  }
  while(b1<=mid){
    c[tmp++]=a[b1];
    b1++;
  }
  while(b2<=r){
    c[tmp++]=a[b2];
    b2++;
  }
  for(int i=l;i<=r;i++)a[i]=c[i];
}
int main(){
  cin>>n;
  for(int i=1;i<=n;i++)cin>>a[i];
  msort(1,n);
  cout<<ans<<endl;
  return 0;
}
posted @   paper_plane  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示