题意叫你求交叉点的个数,转换一下思维,把第一个数看作是i,和它相连接的第二个数看作是ai,当i < j 且 ai > aj时这时才有交叉点,
这样就转换为求逆序对的个数;首先,把他x从小到大排序,x相同的按y从大到小排序,排完序后,在使用合并排序,计算逆序对的个数。
#include<math.h>#include<stdio.h>
#include<limits.h>
#define MAX 1000005
int L[MAX/2],R[MAX/2];
long long sum;
typedef struct NODE{
int e;
int w;
}node;
node A[MAX];
void MERGE(int p,int q,int r)
{
int n1,n2,i,j,k;
n1=q-p+1;
n2=r-q;
for(i=0;i<n1;i++) L[i]=A[p+i].w; // 左部分
L[n1]=INT_MAX;
for(j=0;j<n2;j++) R[j]=A[q+1+j].w; // 右部分
R[n2]=INT_MAX;
i=0; j=0;
for(k=p;k<=r;k++){ // 归并,递增序列
if(L[i]<=R[j]) {
A[k].w=L[i];
i++;
}
else{
sum+=(long long)(n1-i);
A[k].w=R[j];
j++;
}
}
}
void MergeSort(int p,int r)
{
int q;
if(p<r){
q=(p+r)/2;
MergeSort(p,q);
MergeSort(q+1,r);
MERGE(p,q,r);
}
}
int cmp(const void *a,const void *b )
{
if(((node *)a)->e>((node *)b)->e) return 1;
else if((((node *)a)->e==((node *)b)->e) && (((node *)a)->w>((node *)b)->w))
return 1;
return -1;
}
int main()
{
int i,k,j,m,n,t;
scanf("%d",&t);
for(j=1;j<=t;j++){
sum=0;
scanf("%d%d%d",&n,&m,&k);
for(i=0;i<k;i++)
scanf("%d%d",&A[i].e,&A[i].w);
qsort(A,k,sizeof(node),cmp);
MergeSort(0,k-1);
printf("Test case %d: %lld\n",j,sum);
}
system("pause");
return 0;
}