题意:
水平方向有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);}
}