斜率小于0的连线数量 51Nod

来源:互联网 发布:为什么服务器用centos 编辑:程序博客网 时间:2024/05/29 13:42
二维平面上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
42 33 41 54 6
Sample Output

2

运用树状数组和逆序数比较容易想到

一道关于树状数组和逆序数的题跟这个很像——

Ultra-QuickSort

在求逆序数时2 3 2 4这种情况没问题 但是2 4 2 3 就要判断一下

还有个问题是离散化

原来用的方法不适用于有重复元素的 这个是新找到的~~~~~~~

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include <bits/stdc++.h>
using namespace std;
const int maxn=50010;
int c[maxn];


int x[maxn],data[maxn];
int n;
struct node
{
   int x,y;
}a[maxn];




int cmp1(node a,node b)
{
    return a.x<b.x;


}


int lowbit(int i)
{
    return i&(-i);
}
int update(int i,int x)
{
    while(i<=maxn)
    {
        c[i]=c[i]+x;
        i=i+lowbit(i);
    }


}
int query(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=c[i];
        i=i-lowbit(i);


    }


    return sum;
}
void prepare() {
    int i;
    for(int i=1;i<=n;i++)
    data[i]=a[i].y;
    sort(data+1,data+n+1);
    int m=unique(data+1,data+n+1)-data-1;
    for(int i=1;i<=n;i++) a[i].y=lower_bound(data+1,data+m+1,a[i].y)-data;
}
int main()
{


    while(cin>>n)
    {
        memset(c,0,sizeof(c));
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
        }
        prepare();
        
        sort(a+1,a+n+1,cmp1);
        long long sum=0;
        for(int i=1;i<=n;i++)
        {
            update(a[i].y,1);
            sum+=i-query(a[i].y);
            if(a[i-1].x==a[i].x&&i!=1&&a[i-1].y>a[i].y)
            sum--;
        }
        cout<<sum<<endl;
    }


    return 0;
}

原创粉丝点击