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

来源:互联网 发布:新乡启航网络 编辑:程序博客网 时间:2024/05/19 17:22

题意:在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 1010struct 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;}


0 0