POJ 3067 Japan 树状数组求逆序对

题目大意:有两排城市,这两排城市之间有一些路相互连接着,求有多少条路相互交叉。


思路:把所有的路先按照x值从小到大排序,x值相同的按照y值从小到大排序,然后插入边的时候,先找有多少比自己y值小的,这些边的x值一定比自己大,也就是一个逆序对,然后统计起来。记得答案要用long long (__int64)


CODE:


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1010
using namespace std;

struct Complex{
	int x,y;

	bool operator <(const Complex &a)const {
		if(x != a.x)	return x < a.x;
		return y < a.y;
	}
}point[MAX * MAX];

int cases;
int m,n,cnt;
__int64 ans;

__int64 fenwick[MAX];

inline void Initialize();

inline void Fix(int x);
inline __int64 GetSum(int x);

int main()
{
	cin >> cases;
	for(int T = 1;T <= cases; ++T) {
		scanf("%d%d%d",&m,&n,&cnt);
		Initialize();
		for(int i = 1;i <= cnt; ++i)
			scanf("%d%d",&point[i].x,&point[i].y);
		sort(point + 1,point + cnt + 1);
		for(int i = 1;i <= cnt; ++i) {
			ans += GetSum(point[i].y + 1);
			Fix(point[i].y);
		}
		cout << "Test case " << T << ": " << ans << endl;
	}
	return 0;
}

inline void Initialize()
{
	ans = 0;
	memset(fenwick,0,sizeof(fenwick));
}

inline void Fix(int x)
{
	for(;x;x -= x&-x)
		fenwick[x]++;
}
inline __int64 GetSum(int x)
{
	__int64 re = 0;
	for(;x <= n;x += x&-x)
		re += fenwick[x];
	return re;
}



你可能感兴趣的:(poj,树状数组,逆序对)