http://lx.lanqiao.cn/problem.page?gpid=T3012http://lx.lanqiao.cn/problem.page?gpid=T3012
#include<cstdio>
#include<iostream>
#include<cstring>//memset函数头文件
using namespace std;
typedef long long LL;
const int N=1000010;
int h[N],tr[N];
int sum[N];
int n;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int v)
{
for(int i=x;i<=N;i+=lowbit(i))
tr[i]+=v;
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i))
res+=tr[i];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&h[i]);
h[i]++;//因为身高的最小值为零,为了避免树状数组的下标为零,则需将所有的身高都加一
}
//求每个数的前面有多少个数比该数大
for(int i=0;i<n;i++)
{
add(h[i],1);//给树状数组赋值
sum[i]=query(N-1)-query(h[i]);//用最大身高对应的树状数组减去该数对应的树状数组
}
memset(tr,0,sizeof tr);//清空树状数组
//求每个数的后面有多少个数比该数小
for(int i=n-1;i>=0;i--)
{
add(h[i],1);//给树状数组赋值
sum[i]+=query(h[i]-1);//恰好小于该身高对应的树状数组即为比该数小的数量
}
LL res=0;
for(int i=0;i<n;i++)
{
res+=(LL)sum[i]*(sum[i]+1)/2;
}
cout<<res<<endl;
return 0;
}