NYOJ 117 求逆序數 【樹狀數組】

求逆序數

時間限制:2000 ms  |  內存限制:65535 KB
難度:5
描述

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱爲一個逆序。一個排列中逆序的總數就稱爲這個排列的逆序數。

現在,給你一個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
題目鏈接:NYOJ 117 求逆序數 【樹狀數組】

已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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章