求逆序数,不用线段树,只能过50的数据。
用线段树,正着存一遍,逆着存一遍,正着存,求每个数前面比他大的数,
逆着,求后面比他小的数。
然后遍历一遍求和。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <map>
#include <math.h>
#define LL long long
using namespace std;
const int maxn=1000100;
const int inf=1000010;
LL a[maxn],sum[maxn*4];
LL t[maxn];
LL ans;
void PushUp(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void Update(int l,int r,int rt,int p){
if(l==r){
sum[rt]++;
return ;
}
int m=(l+r)>>1;
if(p<=m)
Update(l,m,rt<<1,p);
else
Update(m+1,r,rt<<1|1,p);
PushUp(rt);
}
int Query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)
return sum[rt];
LL ret=0;
int m=(l+r)>>1;
if(L<=m) ret+=Query(L,R,l,m,rt<<1);
if(m<R) ret+=Query(L,R,m+1,r,rt<<1|1);
return ret;
}
int main(){
int n;
LL ans=0;
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%lld",&a[i]);
a[i]+=2;
t[i]+=Query(a[i]+1,inf,1,inf,1);
Update(1,inf,1,a[i]);
}
memset(sum,0,sizeof(sum));
for(int i=n-1;i>=0;--i){
t[i]+=Query(1,a[i]-1,1,inf,1);
Update(1,inf,1,a[i]);
}
for(int i=0;i<n;++i)
ans+=(t[i]*(t[i]+1))/2;
printf("%lld\n",ans);
return 0;
}