题意:就是求出当前这个数前面都多少个比它大的,求总和,其实就是逆序数。
思路:解决逆序数果断用树状数组啊,就是将这些数先从大到小排序,完了再把排完序的下标得到,在按初始的顺序去进行插入树状数组中,还要注意因为这个最大的情况是500000*500000/2,所以要用long long。
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500100;
int n;
long long l[maxn];
struct node
{
int a;
int num;
};
node t[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x)
{
while(x<=n)
{
l[x]++;
x+=lowbit(x);
}
}
long long sum(int x)
{
long long cnt=0;
while(x)
{
cnt+=l[x];
x-=lowbit(x);
}
return cnt;
}
int cmp1(struct node p,struct node q)
{
return p.a>q.a;
}
int cmp2(struct node p,struct node q)
{
return p.num<q.num;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i].a);
t[i].num=i;
}
sort(t+1,t+n+1,cmp1); //先按数的从大到小排序
for(int i=1;i<=n;i++)
{
t[i].a=i; //把对应的排序后的下标存起来
}
sort(t+1,t+1+n,cmp2); //再按以前的初始的下标从小到大排序 就是初始时的顺序了
memset(l,0,sizeof(l));
long long ans=0;
for(int i=1;i<=n;i++)
{
ans+=sum(t[i].a); //要先找之前节点的个数,之后再把自身存进去,要不要减一
add(t[i].a);
}
printf("%lld\n",ans);
}
return 0;
}