题目:
二维平面上N个点之间共有C(n,2)条连线。求这C(n,2)条线中斜率小于0的线的数量。
二维平面上的一个点,根据对应的X Y坐标可以表示为(X,Y)。例如:(2,3) (3,4) (1,5) (4,6),其中(1,5)同(2,3)(3,4)的连线斜率 < 0,因此斜率小于0的连线数量为2。
Input
第1行:1个数N,N为点的数量(0 <= N <= 50000)
第2 - N + 1行:N个点的坐标,坐标为整数。(0 <= Xii, Yii <= 10^9)
Output
输出斜率小于0的连线的数量。(2,3) (2,4)以及(2,3) (3,3)这2种情况不统计在内。
Sample Input
4
2 3
3 4
1 5
4 6
Sample Output
2
思路:
求斜率小于0的连线也就是求一个点右下方有多少个点,同时题目说了不考虑斜率为0和斜率不存在的情况.首先点的坐标很大所以先要离散化先将点按照y轴排序然后对他们进行编号,然后再按照x轴排一次序就可以了
然后就是根据求逆序数的方法,每插一个数进入数组就查询一次前面x坐标比他大的有多少
注意要将斜率为0的记录一下,最后答案要减去这种情况
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 123467;
int T,n,q;
int c[maxn];
struct Node
{
int x,y,id;
}node[maxn];
bool cmpy(Node a,Node b)
{
if(a.y!=b.y)
return a.y<b.y;
else
return a.x<b.x;
}
bool cmpx(Node a,Node b)
{
if(a.x!=a.y)
return a.x<b.x;
else if(a.x==a.y)
return a.y<b.y;
}
int lowbit(int x)
{
return x&(-x);
}
int query_sum(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void update(int x, int v)
{
while(x<=n)
{
c[x]+=v;
x+=lowbit(x);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int tot=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].x,&node[i].y);
}
sort(node+1,node+n+1,cmpy);
node[1].id=++tot;
for(int i=2;i<=n;i++)
{
if(node[i].y==node[i-1].y)
node[i].id=tot;
else
node[i].id=++tot;
}
sort(node+1,node+n+1,cmpx);
int k=0;
int ans=0;
update(node[1].id,1);
for(int i=2;i<=n;i++)
{
ans+=(query_sum(n)-query_sum(node[i].id));
update(node[i].id,1);
if(node[i].x==node[i-1].x&&node[i].id<node[i-1].id)//斜率为0的情况
k++;
}
printf("%d\n",ans-k);
}
return 0;
}