poj 3067(树状数组)

题意:有两排城市,这两排之间有一些城市之间有连接的道路,给出所有道路,问有多少道路是相交的,交点不为城市所在点。

思路:开始暴力的做出来了,时间还挺短的,但知道这题可以用树状数组做,就做了一下。我们把所给的公路的坐标排序,按a升序,a相同按b升序。我们可以看出,每个点跟自己左上角和右下角的点都有交点,为了不重复统计,只统计每个点左上角的点数。就是求逆序数的个数,然后用点的个数减去就可以了。





#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int N=1010;
struct node
{
	int x,y;
}p[N*N];
int S[N],n,m,k;
void plus(int i)
{
	while(i<=m)
	{
		S[i]++;
		i+=(i&(-i));
	}
}
__int64 findsum(int i)
{
	__int64 sum=0;
	while(i>0)
	{
		sum+=S[i];
		i-=(i&(-i));
	}
	return sum;
}
int cmp(void const *a,void const *b)
{
	node *c,*d;
	c=(node *)a;
	d=(node *)b;
	if(c->x!=d->x)
		return c->x-d->x;
	return c->y-d->y;
}
int main()
{
	int i,t,op=1;
	__int64 sum;
	scanf("%d",&t);
	while(t--)
	{
		sum=0;
		memset(S,0,sizeof(S));
		scanf("%d%d%d",&n,&m,&k);
		for(i=1;i<=k;i++)
			scanf("%d%d",&p[i].x,&p[i].y);
		qsort(p+1,k,sizeof(p[0]),cmp);
		for(i=1;i<=k;i++)
		{
			sum+=(i-1-findsum(p[i].y));
			plus(p[i].y);
		}
		printf("Test case %d: %I64d\n",op++,sum);
	}
	return 0;
}

暴力代码:



#include<stdio.h>
#include<string.h>
const int N=1100;
bool map[N][N];
int b[N];
int main()
{
	int i,j,x,y,n,m,k,t,op=1;
	__int64 sum;
	scanf("%d",&t);
	while(t--)
	{
		sum=0;
		scanf("%d%d%d",&n,&m,&k);
		memset(map,false,sizeof(map));
		memset(b,0,sizeof(b));
		for(i=1;i<=k;i++)
		{
			scanf("%d%d",&x,&y);
			{
				map[x][y]=true;
				b[y]++;
			}
		}
		for(i=1;i<=n;i++)
		{
			k=0;//j点上面所有点的边的数量
			for(j=1;j<=m;j++)
			{
				if(map[i][j])//i,j之间有边
				{
					b[j]--;//去掉这条边
					sum+=k;
				}
				k+=b[j];
			}
		}
		printf("Test case %d: %I64d\n",op++,sum);
	}
	return 0;
}


你可能感兴趣的:(编程,算法,百度,ACM,树状数组)