HDU 3465 Life is a Line 树状数组求逆序数

Life is a Line

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 192 Accepted Submission(s): 71
 
Problem Description
There is a saying: Life is like a line, some people are your parallel lines, while others are destined to meet you.
Maybe have met, maybe just a matter of time, two unparallel lines will always meet in some places, and now a lot of life (i.e. line) are in the same coordinate system, in a given open interval, how many pairs can meet each other?

 
Input
There are several test cases in the input.

Each test case begin with one integer N (1 ≤ N ≤ 50000), indicating the number of different lines.
Then two floating numbers L, R follow (-10000.00 ≤ L < R ≤ 10000.00), indicating the interval (L, R).
Then N lines follow, each line contains four floating numbers x1, y1, x2, y2 (-10000.00 ≤ x1, y1, x2, y2 ≤ 10000.00), indicating two different points on the line. You can assume no two lines are the same one.

The input terminates by end of file marker.
 
Output
For each test case, output one integer, indicating pairs of intersected lines in the open interval, i.e. their intersection point’s x-axis is in (l, r).

 
Sample Input
3
0.0 1.0
0.0 0.0 1.0 1.0
0.0 2.0 1.0 2.0
0.0 2.5 2.5 0.0
 
Sample Output
1
 
Author
题目大意:

给出  一个区间  ( l  r),给出 n条直线,问这些直线有多少交点在区间内。

思路;

我们先求出给出每条直线在  l   r  上交点,如果   两条直线相交,那么    a  直线在 l  上的交点 在  b  直线在  l  上的交点下面  并且,a 直线在 r 上的交点在  b 直线与 r  交点的上方,或者是反过来,因此想到用逆序数来解决这个问题。
我们首先按照在  l  上交点 从小到大排序,然后编上序号,按照r上的顺序,从大到小排序,统计就可以了。
特殊考虑的地方:

直线和 y 轴平行。

实话,printf  比 cout 快

AC代码:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
struct qqq
{
    double  ll;
    double  rr;
    int pos;
}qq[50005];
bool cmp1(const qqq &a,const qqq &b)
{
    if(a.ll==b.ll)
        return a.rr<b.rr;
    return a.ll<b.ll;
}
bool cmp2(const qqq &a,const qqq &b)
{
    if(a.rr==b.rr)
    {
        return a.ll>b.ll;
    }
    return a.rr>b.rr;
}
int a[50005];
int MAXN=50005;
int	lowbit(int	x)
{
    return	x&(-x);
}
void add(int x,int add)
{
    while(x<=MAXN)
    {
        a[x]+=add;
        x+=lowbit(x);
    }
}
int	get_sum(int	x)
{
    int	ret=0;
    while(x!=0)
    {
        ret+=a[x];
        x-=lowbit(x);
    }
    return	ret;
}
int main()
{
    int n;
    double l,r;
    double x1,y1,x2,y2;
    double k,b;
    while(~scanf("%d",&n))
    {
        int t=0;
        int tt=0;
        scanf("%lf%lf",&l,&r);
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            if(x1==x2)
            {
                if(x1>l&&x1<r)
                {
                    tt++;
                }
                continue;
            }
            k=(y2-y1)/(x2-x1);
            b=y1-k*x1;
            qq[t].ll=l*k+b;
            qq[t++].rr=r*k+b;
        }
        sort(qq,qq+t,cmp1);
        for(int i=0;i<t;i++)
        {
            qq[i].pos=i+1;
        }
        sort(qq,qq+t,cmp2);
        memset(a,0,sizeof(a));
        int ans=0;
        for(int i=0;i<t;i++)
        {
            add(qq[i].pos,1);
            ans+=get_sum(qq[i].pos-1);
        }
        printf("%d\n",ans+tt*t);
    }
}



 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值