题意:一个国家分为东部和西部,分别包括n个和m个城市,在城市之间建k条路,问有多少个交点。(不存在三边交与一点的情况)

思路:很容易想到转化为求逆序数,可以用归并排序来求,也可以用树状数组。树状数组实现要比归并简单一点。。

需要注意:k<=10^6,最后的结果要用__int64 存储

归并:

# include<stdio.h>
# include<string.h>
# include<stdlib.h>
struct node{
	int from,to,next;
}edge[1000005];
int head[1005],tol,num[1000005];
__int64 count;
int temp[1000005];
int cmp(const void *a,const void *b)
{
	return *(int *)a - *(int *)b;
}
void add(int a,int b)
{
	edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
}
void merge(int l,int mid,int r)
{
	int a1,a2,k,i;
	
	a1=l;
	a2=mid+1;
	k=0;
	while(a1<=mid && a2<=r)
	{
		if(num[a1]<=num[a2])
		{
			temp[++k]=num[a1];
			count+=a2-mid-1;
			a1++;
		}
		else 
		{
			temp[++k]=num[a2];
			a2++;
		}
	}
	while(a1<=mid)
	{
		temp[++k]=num[a1];
		count+=r-mid;
		a1++;
	}
	while(a2<=r)
	{
		temp[++k]=num[a2];
		a2++;
	}
	for(i=1;i<=k;i++)
		num[i+l-1]=temp[i];
}
void mergesort(int l,int r)
{
	int mid=(l+r)/2;
	if(r>l)
	{
		mergesort(l,mid);
		mergesort(mid+1,r);
		merge(l,mid,r);
	}
}
int main()
{
	int i,j,n,m,ncase,s[1005],k,ans,mm,a,b,t;
	scanf("%d",&ncase);
	for(t=1;t<=ncase;t++)
	{
		scanf("%d%d%d",&n,&m,&k);
		memset(head,-1,sizeof(head));
		tol=0;
		for(i=0;i<k;i++)
		{
			scanf("%d%d",&a,&b);
			add(a,b);
		}
	
		ans=0;
		for(i=1;i<=n;i++)
		{	
			mm=0;
			for(j=head[i];j!=-1;j=edge[j].next)
				s[++mm]=edge[j].to;
			qsort(s+1,mm,sizeof(s[1]),cmp);
			for(j=1;j<=mm;j++)
				num[++ans]=s[j];
		}
		count=0;
		mergesort(1,ans);
		printf("Test case %d: %I64d\n",t,count);
	}
	return 0;
}

 

树状数组:

View Code
 1 # include<stdio.h>
2 # include<string.h>
3 # include<stdlib.h>
4 struct node{
5 int from,to,next;
6 }edge[1000005];
7 int head[1005],tol,count[1005],m;
8 int cmp(const void *a,const void *b)
9 {
10 return *(int *)a - *(int *)b;
11 }
12 void add(int a,int b)
13 {
14 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
15 }
16 void insert(int i)
17 {
18 while(i<=m)
19 {
20 count[i]++;
21 i+=i&(-i);
22 }
23 }
24 int query(int i)
25 {
26 int sum=0;
27 while(i>=1)
28 {
29 sum+=count[i];
30 i-=i&(-i);
31 }
32 return sum;
33 }
34 int main()
35 {
36 int i,j,n,ncase,s[1005],k,ans,mm,a,b,t,num;
37 __int64 sum;
38 scanf("%d",&ncase);
39 for(t=1;t<=ncase;t++)
40 {
41 scanf("%d%d%d",&n,&m,&k);
42 memset(head,-1,sizeof(head));
43 tol=0;
44 for(i=0;i<k;i++)
45 {
46 scanf("%d%d",&a,&b);
47 add(a,b);
48 }
49 memset(count,0,sizeof(count));
50 sum=0;
51 ans=0;
52 for(i=1;i<=n;i++)
53 {
54 mm=0;
55 for(j=head[i];j!=-1;j=edge[j].next)
56 s[++mm]=edge[j].to;
57 qsort(s+1,mm,sizeof(s[1]),cmp);
58 for(j=1;j<=mm;j++)
59 {
60 num=query(s[j]);
61 sum+=ans-num;
62 insert(s[j]);
63 ans++;
64 }
65 }
66 printf("Test case %d: %I64d\n",t,sum);
67 }
68 return 0;
69 }

posted on 2011-09-29 09:28  奋斗青春  阅读(244)  评论(0编辑  收藏  举报