您的位置:首页 > Web前端

HDU 3465 Life is a Line 逆序数

2014-11-04 22:34 525 查看

Life is a Line

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)

Total Submission(s): 1691 Accepted Submission(s): 383



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


/*
HDOJ 3465 逆序数 

Line都是直线,不是线段,没有端点,输入的点只是用于确定这条直线的位置 
对每条直线与x=L,和x=r的交点分别为xl,xr,两直线在(L,R)相交,必然有 
xl1>xl2&&xr1<xr2 或者 xl1<xl2&&xr1>xr2,(A.L-B.L)*(A.R-B.R)<0
 
如果将与L的交点从小到大排,那么当相应的R的交点出现一个逆序数对就表示有两直线有交点.
 先将所有直线根据l递增排序,之后编号1~n,再根据r递减排序,得到一个编号序列。
 例如3412,递减,其中r3>r4>r1>r2, 又编号:l1<l2<r3<r4,1234=>所以12 34 所以3和4有交点,1和2有交点。
 这符合逆序数的关系:一个数的逆序数是在它之前比他大的数的个数, 
当然这里是小的数,原因是为了方便树状数组处理。所以只要根据上述方法排序再求逆序数即可。 
1.与y轴平行得线,只要这样的线在(l,r)范围内,则必定跟别的不平行线相交。
	所以计算下个数在乘积 
2.l和r相同的情况。当l相同时,r递增排序;当r相同时,l递减排序。
	就能使在l和r上的交点不计算在内。 
	
参考别人的树状数组
    树状数组可以说是线段树的简化,处理单一,但写起来简便。 
    两个函数: 
    add(x,val),时c[x]+=val; 
    sum(x),求c[1]+c[2]+...+c[x];  
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

#define lowbit(x) (x&(-x)) 
const int N=5e4+10;
struct node{
	double a,b;
	int num;
};
node e
;
int c
;
double l,r; 

int cmp1(node x,node y) //left 递增排序 
{  
    if(x.a==y.a)
		return x.b<y.b;  
    return x.a<y.a;  
}
  
int cmp2(node x,node y) //right 递减排序 
{  
    if(x.b==y.b)
		return x.a>y.a;  
    return x.b>y.b;  
}  

void add(int x,int val)  
{  
    while(x<N)  
    {  
        c[x]+=val;  
        x+=lowbit(x);  
    }  
}  

int sum(int x)  
{  
    int ans=0;  
    while(x>0)  
    {  
        ans+=c[x];  
        x-=lowbit(x);  
    }  
    return ans;  
}  

int main()
{
	int n;
	int t,tt,i,j,ans;
	double x1,y1,x2,y2,k,b;
	
	while(scanf("%d",&n)!=EOF)
	{
		t=tt=0;
		ans=0;
		scanf("%lf%lf",&l,&r);
		for(i=0;i<n;i++)
		{
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);//两个点的横纵坐标 
			if(x1==x2)//横坐标相等  表示竖直的线 平行与y轴 
			{
				if(l<x1&&x1<r)
					tt++;
				continue;
			}
			k=(y2-y1)/(x2-x1);//y=kx+b
			b=y1-k*x1;
			e[t].a=l*k+b;
			e[t++].b=r*k+b;
		}
		sort(e,e+t,cmp1);
		for(i=0;i<t;i++)//编号 
			e[i].num=i+1;
		sort(e,e+t,cmp2);//递减排序 3412 
		memset(c,0,sizeof(c));
		for(i=0;i<t;i++)//统计
		{
			add(e[i].num,1);
			ans+=sum(e[i].num-1);
		} 
		printf("%d\n",ans+tt*t);//加上平行y轴的直线所产生的交点  
	} 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: