题意:
水平方向有2n个城市点,他们分别按顺序分布在平行的两条直线上,编号都是从1到n。然后现在在上直线与下直线的两个城市点之间建公路,一共建k条公路。问你这k条公路一共有多少个交点(保证最多只有两条公路会交于同一点)?
题解:
注意题目中两边的岛是这么分布的:
1 2 3 4
1 2 3 4
且一个点最多只有两条边相交,不可能出现3线共点的情况。假设1,4是一条边,那么第二行4前面的1,2,3,任意一个去和上面的2,3,4,任意连接一下都会和刚才那个边产生一个交点。
所以现在我们对所有的边按照在y行上的坐标从小到大排序,如果y相同,则按x从小到大排序。那么(x,y)边上有多少交点,只需要看x前面有多少比他大的就可以了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1000+10;
int c[maxn];
struct node
{
int x,y;
bool operator <(const node& a)const
{
if(y!=a.y)
return y<a.y;
return x<a.x;
}
}ns[maxn*maxn];
int lowbit(int x)
{
return x & -x;
}
int sum(int x)
{
int res = 0;
while(x>0)
{
res+=c[x];
x -= lowbit(x);
}
return res;
}
void add(int x,int v)
{
while(x<maxn)
{
c[x]+=v;
x+=lowbit(x);
}
}
int main()
{
int t;cin>>t;
for(int kase=1;kase<=t;kase++)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&ns[i].x,&ns[i].y);
}
sort(ns+1,ns+1+k);
long long ans = 0;
memset(c,0,sizeof c);
for(int i=1;i<=k;i++)
{
ans += i-1-sum(ns[i].x);
add(ns[i].x,1);
}
printf("Test case %d: %lld\n",kase,ans);
}
}