求逆序數
- 描述
-
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱爲一個逆序。一個排列中逆序的總數就稱爲這個排列的逆序數。
現在,給你一個N個元素的序列,請你判斷出它的逆序數是多少。
比如 1 3 2 的逆序數就是1。
- 輸入
- 第一行輸入一個整數T表示測試數據的組數(1<=T<=5)
每組測試數據的每一行是一個整數N表示數列中共有N個元素(2〈=N〈=1000000)
隨後的一行共有N個整數Ai(0<=Ai<1000000000),表示數列中的所有元素。
數據保證在多組測試數據中,多於10萬個數的測試數據最多隻有一組。 - 輸出
- 輸出該數列的逆序數
- 樣例輸入
-
2 2 1 1 3 1 3 2
- 樣例輸出
-
0 1
已AC代碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 1000010
#define LL long long
using namespace std;
struct NODE{
int pos,val;
}s[M];
LL tree[M],a[M];
int n;
bool cmp(NODE a,NODE b)
{
if(a.val==b.val)
return a.pos>b.pos;
return a.val>b.val;
}
int lowbit(int x)
{
return x&(-x);
}
void updata(int pos)
{
while(pos<=n)
{
tree[pos]+=1;
pos+=lowbit(pos);
}
}
int Query(int pos)
{
int sum=0;
while(pos>0)
{
sum+=tree[pos];
pos-=lowbit(pos);
}
return sum;
}
int main()
{
int T,i;
scanf("%d",&T);
while(T--)
{
memset(tree,0,sizeof(tree));
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%d",&s[i].val);
s[i].pos=i;
}
sort(s+1,s+n+1,cmp);
LL sum = 0;
for(i = 1; i <= n; i++)
{
updata(s[i].pos);
if(s[i].pos == 1)
continue;
sum += Query(s[i].pos - 1);
}
printf("%lld\n",sum);
}
return 0;
}