HDOJ 题目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): 1705    Accepted Submission(s): 388


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
iSea @ WHU
 

Source
 

Recommend
zhouzeyong   |   We have carefully selected several similar problems for you:   3461  3467  3468  3464  3462 
 
  1. 题意:输入n条直线,和区间(l,r)(注意不含l和r)。问x在(l,r)内时,总共有多少个交点。 
  2.     题解:先学怎么判断交点。对于两条直线line1和line2,他们在横坐标l和r位置上纵坐标分别为l1,r1,l2,r2. 
  3. 则(l1-l2)*(r1-r2)<0时有交点。 
  4.     通过上面的方法我们可以想到逆序数的解法。 
  5.     先将所有直线根据l递增排序,之后编号1~n,再根据r递减排序,得到一个编号序列。例如3412,其中r3>r4>r1>r2, 
  6. 又l1<l2<r3<r4,所以3和4有交点,1和2有交点。这符合逆序数的关系:一个数的逆序数是在它之前比他大的数的个数, 
  7. 当然这里是小的数,原因是为了方便树状数组处理。所以只要根据上述方法排序再求逆序数即可。 
  8.     不过有些特殊情况需要处理: 
  9.     1.与y轴平行得线,只要这样的线在(l,r)范围内,则必定跟别的不平行线相交。所以计算下个数在乘积就OK。 
  10.     2.l和r相同的情况。当l相同时,r递增排序;当r相同时,l递减排序。就能使在l和r上的交点不计算在内。 
  11. 死活不知道我注释的那求逆序对的写法哪错了,先收藏一下吧
  12. ac代码
  13. #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct s
    {
    	double a,b;
    	int num;
    }c[50010];
    int cmp1(s x,s y)
    {
    	if(x.a==y.a)
    		return x.b<y.b;
    	return x.a<y.a;
    }
    int cmp2(s x,s y)
    {
    	if(x.b==y.b)
    		return x.a>y.a;
    	return x.b>y.b;
    }
    int d[50010],t;
    int low(int x)
    {
    	return x&(-x);
    }
    void add(int p,int q)
    {
    	while(p<=t)
    	{
    		d[p]+=q;
    		p+=low(p);
    	}
    }
    int sum(int p)
    {
    	int ans=0;
    	while(p>0)
    	{
    		ans+=d[p];
    		p-=low(p);
    	}
    	return ans;
    }
    int cot[100010];
    int main()
    {
    	int n;
    	while(scanf("%d",&n)!=EOF)
    	{
    		double l,r;
    		int i,tt=0,ans=0;
    		t=0;
    		scanf("%lf%lf",&l,&r);
    		for(i=0;i<n;i++)
    		{
    			double x1,x2,y1,y2,k,bn;
    			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    			if(x1==x2)
    			{
    				if(x1<r&&x1>l)
    					tt++;
    				continue;
    			}
    			k=(y1-y2)/(x1-x2);
    			bn=y1-k*x1;
    			c[t].a=k*l+bn;
    			c[t++].b=k*r+bn;
    		}
    		sort(c,c+t,cmp1);
    		for(i=0;i<t;i++)
    		{
    			c[i].num=i+1;
    		}
    		sort(c,c+t,cmp2);
    		memset(d,0,sizeof(d));
    		memset(cot,0,sizeof(cot));
    		/*for(i=0;i<t;i++)
    		{
    			cot[c[i].num]=i+1;
    		}
    		for(i=1;i<=t;i++)
    		{
    			add(cot[i],1);
    			ans+=i-sum(cot[i]);
    		}*/
    		for(i=0;i<t;i++)
    		{
    			add(c[i].num,1);
    			ans+=sum(c[i].num-1);
    		}
    		printf("%d\n",ans+tt*t);
    	}
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值