树状数组求逆序对裸题,先来个离散化,然后树状数组做逆序对,每把一个数字(a[i])处理之前,答案加上sum(a[i),然后再在树状数组中对于a[i]的位置上加1,
这样的话,每次树状数组取前缀和的时候,取到的前缀和就是在a[i]之前比a[i]大的数字的个数
贴代码:
Problem: 2299 User: 76120114
Memory: 7912K Time: 391MS
Language: G++ Result: Accepted
Source Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=500005;
int a[maxn],t[maxn];
int c[maxn];
struct node
{
int pos,num;
}e[maxn];
bool cmp(node a,node b)
{
return a.num<b.num;
}
int lowbit(int x)
{
return x&(-x);
}
void insert(int x)
{
for(int i=x;i<maxn;i+=lowbit(i)) c[i]+=1;
}
int sum(int x)
{
int s=0;
for(int i=x;i>0;i-=lowbit(i)) s+=c[i];
return s;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
scanf("%d",&e[i].num);
e[i].pos=i;
}
sort(e+1,e+n+1,cmp);
int temp=n;
for(int i=1;i<=n;i++) e[i].num=temp--;
for(int i=1;i<=n;i++) a[e[i].pos]=e[i].num;
long long ss=0;
for(int i=1;i<=n;i++)
{
ss+=sum(a[i]);
insert(a[i]);
}
printf("%lld\n",ss);
}
return 0;
}