b[i]为原数组,表示当前数i出现次数
用树状数组c[i]维护前i个b[i]的和,即当前<=i的数的个数
只要依次扫插入并统计数a[i]之前比a[i]大的数的个数即可求得逆序对
需要离散化
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <set> #define ll long long using namespace std; const int MAXN=5e5+10; int n; ll ans; int a[MAXN],x[MAXN],c[MAXN]; inline int in() { int x=0,flag=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') flag=-1;ch=getchar();} while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*flag; } bool cmp(int x,int y) { return a[x]<a[y]; } int lowbit(int x) {return x&(-x);} int query(int x) { int cnt=0; while (x) { cnt+=c[x]; x-=lowbit(x); } return cnt; } void updata(int x,int val) { while (x<=n) { c[x]+=val; x+=lowbit(x); } } int main() { n=in(); for (int i=1;i<=n;i++) a[i]=in(),x[i]=i; sort(x+1,x+n+1,cmp); for (int i=1;i<=n;i++) a[x[i]]=i; for (int i=1;i<=n;i++) { //printf("%d ",query(a[i])); ans+=(ll)(i-1-query(a[i])); updata(a[i],1); } //for (int i=1;i<=n;i++) printf("%d ",a[i]); printf("%lld",ans); return 0; }