题意:有两排城市,这两排之间有一些城市之间有连接的道路,给出所有道路,问有多少道路是相交的,交点不为城市所在点。
思路:开始暴力的做出来了,时间还挺短的,但知道这题可以用树状数组做,就做了一下。我们把所给的公路的坐标排序,按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; }