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