Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, … from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.
输入:
The input file starts with T - the number of test cases. Each test case starts with three numbers – N, M, K. Each of the next K lines contains two numbers – the numbers of cities connected by the superhighway. The first one is the number of the city on the East coast and second one is the number of the city of the West coast.
输出:
For each test case write one line on the standard output:
Test case (case number): (number of crossings)
Sample Input
1
3 4 4
1 4
2 3
3 2
3 1
Sample Output
Test case 1: 5
题意:
就是从一个地方到另一个地方要修一些路,每一个地方有一些城市,路就是在这些城市之间修筑的
1 1
2 2
3 3
4 4
A地方 B地方
这像这样在城市之间建路,问最后这些路有多少个交叉点
做法:
对于求逆序对可以用线状数组还可以用线段树,这里我们主要说线段树方法
只有两个地方对应的城市连起来才会交叉口为0(前提是两个地方的城市数目一样),所以我们只需要将他们从原来的乱序,排序到他们的逆序对为0即可
逆序对就是在一个序列a、b、c、d。如果a>b(或他们任意两个数前面的大于后面的)就成为一个逆序对
可以看一下归并排序,他的算法就可以求出来一个序列中的逆序对的数目
但是这个只能求一个序列的逆序数,但是我们这个题目是两个数的连接
所以我们可以把他们转化成求一个序列的逆序对
我们知道两条路
a——b
c——d
当a<c && b>d的时候会出现交叉,当然不止这一种,但是我们可以对A/B两个地方中的一个进行排序(我按的从小到大),然后再求另一个地方的逆序对
线段树操作:
就是如果这个城市在这个区间中那么这个区间就加一
注意:
要先查找再去更新
因为我们是让A地方的城市从小到大,所以只要前面A地方的城市连接B地方的城市的次序大于目前这个,那么他们就会有交点
//思路:这题画个图就一目了然了,我们将获得所有边以y坐标从小到大排序,
//如果y坐标相同,则x坐标小的排在前面。那么我们当前扫描到的xi,yi边有多少个交点?
//只要看xi前面有多少个xj(j<=i-1)是大于xi的就行。这就是xi的逆序数。
//该题就转化为求排序后的x坐标的逆序数之和了。结果要用long long保存。
//只要知道这个思路,那么树状数组和线段树都可以做
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000005;
int sum[maxn<<2];
struct shudui
{
int l,r;
}w[maxn];
bool mmp(shudui x,shudui y)
{
if(x.l==y.l)
return x.r<y.r;
else return x.l<y.l;
}
void update(int L,int l,int r,int rt)
{
if(l>L || L>r) return;
sum[rt]++;
if(l==r) return; //注意加这一句,要不然循环出不来
int mm=(l+r)>>1;
update(L,l,mm,rt<<1);
update(L,mm+1,r,rt<<1|1);
}
int query(int L,int l,int r,int rt)
{
if(L>r) return 0;
if(L<=l) return sum[rt];
int mm=(l+r)>>1;
return query(L,l,mm,rt<<1)+query(L,mm+1,r,rt<<1|1);
}
int main()
{
int t,p=0;
long long ans=0;
scanf("%d",&t);
while(t--)
{
p++;
ans=0;
memset(sum,0,sizeof(sum));
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;++i)
{
scanf("%d%d",&w[i].l,&w[i].r);
}
sort(w,w+k,mmp);
int maxx=max(m,n);
for(int i=0;i<k;++i)
{
//printf("%d**
",w[i].r);
ans+=(long long)query(w[i].r+1,1,maxx,1);
update(w[i].r,1,maxx,1);
}
printf("Test case %d: %lld
",p,ans);
}
return 0;
}