poj 3067 树状数组(高速公路的交叉数量)

题意:在Japan的东西两边都有海岸线。两边分别有n,m个城市,他们的编号分别都为1....n, 1....m。要在东西海岸的城市间建立一些高速路,通过点对给出。求所有的交点有多少个(一个交点保证只有两条路穿过)。

思路:树状数组。具体来说,如果把1...m重新从大到小编号(具体的操作可以用m+1减去原来编号)。则问题变成求一对儿的x和y完全大于另一对儿的对数。这与苹果那题便如出一辙。将(n,m)按照m从小到大排序,相同的按照n从大到小,查找sum(n-1)即可。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 1010
struct node{
	int x,y;
}p[N*N];
__int64 tree[N];
int T,c=0;
int n,m,k;
int cmp(const struct node *a,const struct node *b){
	if((*a).y == (*b).y)
		return (*b).x - (*a).x;
	return (*a).y - (*b).y;
}
int lowbit(int x){
	return x&(-x);
}
void add(int x){
	int i;
	for(i = x;i<=n;i+=lowbit(i))
		tree[i]++;
}
__int64 sum(int x){
	int i;
	__int64 res=0;
	for(i = x;i>=1;i-=lowbit(i))
		res += tree[i];
	return res;
}
int main(){
	freopen("a.txt","r",stdin);
	scanf("%d",&T);
	while(c++<T){
		int i,a,b;
		__int64 res=0;
		memset(tree,0,sizeof(tree));
		scanf("%d %d %d",&n,&m,&k);
		for(i = 0;i<k;i++){
			scanf("%d %d",&a,&b);
			p[i].x = a;
			p[i].y = m+1-b;
		}
		qsort(p,k,sizeof(struct node),cmp);
		for(i = 0;i<k;i++){
			res += sum(p[i].x-1);
			add(p[i].x);
		}
		printf("Test case %d: %I64d\n",c,res);
	}
	return 0;
}


你可能感兴趣的:(poj 3067 树状数组(高速公路的交叉数量))