poj3067(树状数组)

题意:日本计划在东边的城市和西边的城市中建路,东边的点从1.....n,西边的点从1..........m,求这些点连起来后有多少交叉......

思路:一开始看到这个题目,完全没有思路。想了一下,把图画出来后,发现.....原来是树状数组的题目。

反思:这道题目思路很简单,但是我还是wa了3次,因为我没有将和定义为int64位......以前做树状数组题,也有好几次因为这个问题wa的,以后对于sum,一律将其赋值为64位的........................

#include<iostream>

#include<algorithm>

using namespace std;

#define max 1000005

struct node 

{

	int a,b;

}t[max];

int cmp(node &p,node &q)             //对东边的城市进行升序排序,当东边为同一个点时,对西边的点进行升序排序,然后就是求逆序数了

{

	if(p.a<q.a)

		return 1;

	else if(p.a==q.a&&p.b<q.b)

		return 1;

	else

		return 0;

}

int c[max],n,m;

int lowbit(int x)

{

	return x&(-x);

}

void updata(int i,int j)

{

	while(i<=m)

	{

		c[i]+=j;

		i+=lowbit(i);

	}

}

__int64 getsum(int x)

{

	__int64 sum=0;

	while(x>0)

	{

		sum+=c[x];

		x-=lowbit(x);

	}

	return sum;

}

int main()

{

	int text,j=0;

	scanf("%d",&text);

	while(text--)

	{

		int k,i;

		memset(c,0,sizeof(c));

		scanf("%d%d%d",&n,&m,&k);

		for( i=1;i<=k;i++)

		{

			scanf("%d%d",&t[i].a,&t[i].b);

		}

		sort(t+1,t+1+k,cmp);

		__int64 sum=0;

		//for(i=1;i<=k;i++)

		//	printf("%d %d\n",t[i].a,t[i].b);

		for( i=1;i<=k;i++)

		{

			updata(t[i].b,1);

			sum+=i-getsum(t[i].b);

		}

		printf("Test case %d: %I64d\n",++j,sum);

	}

	return 0;

}

 

 

你可能感兴趣的:(树状数组)