题目大意:
给你一组序列,求得该组序列的逆序对;
解题思路:
这道题目可以用树状数组也可以用线段树;
在插入的过程中不断的查询当前位置之前的数字个数和,然后用当前的位置减去这个和即可,因为如果查找到比你小的数,则说明它们在序列中当前位置的前面,而现在插入的个数为当前数字的位置,所以用插入的个数减去比当前位置小的个数,即为在当前位置比当前位置数字大的已经插入的数字的个数,即逆序对;
但是这道题目需要注意的是数据的范围是0-999999999,所以需要离散化;
离散的方法,记录原来的位置,然后从小到大排序,然后按照次序赋予当前每个数的位置,然后按照原来的顺序插入当前的位置即可;感觉好绕,看代码!!!!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500010
int n;
int c[maxn];
int now[maxn];
struct Node{
int pos;
int val;
Node(){}
Node(int a,int b):pos(a),val(b){}
bool operator <(const Node &t)const{return val<t.val;}
}node[maxn];
int lowbit(int x)
{
return x&(-x);
}
void updata(int x)
{
while(x<=n)
{
c[x]+=1;
x+=lowbit(x);
}
}
int getsum(int x)
{
long long sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
while(scanf("%d",&n),n)
{
long long ans=0;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
node[i]=Node(i,num);
}
sort(node+1,node+n+1);
for(int i=1;i<=n;i++)
now[node[i].pos]=i;
for(int i=1;i<=n;i++)
{
ans+=i-1-getsum(now[i]);
updata(now[i]);
}
printf("%lld\n",ans);
}
}