hdu 3465 Life is a Line 树状数组求逆序数
2013-09-24 19:47
393 查看
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <iostream> #include <algorithm> using namespace std; #define lowbit(x) (x&(-x)) const int maxn=5e4+10; struct node{ double a,b; int num; }e[maxn]; double l,r; int c[maxn]; int cmp1(node x,node y) { if(x.a==y.a)return x.b<y.b; return x.a<y.a; } int cmp2(node x,node y) { if(x.b==y.b)return x.a>y.a; return x.b>y.b; } void add(int x,int val) { while(x<maxn) { c[x]+=val; x+=lowbit(x); } } int sum(int x) { int s=0; while(x>0) { s+=c[x]; x-=lowbit(x); } return s; } int main() { int n; while(scanf("%d",&n)!=EOF) { int t,tt,i,j,ans=0; double x1,y1,x2,y2,k,b; t=tt=0; scanf("%lf%lf",&l,&r); for(i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); if(x1==x2) { if(x1<r&&x1>l)tt++;//平行y轴,且在(l,r)内的线 continue; } k=(y2-y1)/(x2-x1); 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); 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轴的直线所产生的交点 } return 0; } /* 题意:输入n条直线,和区间(l,r)(注意不含l和r)。问x在(l,r)内时,总共有多少个交点。 题解:先学怎么判断交点。对于两条直线line1和line2,他们在横坐标l和r位置上纵坐标分别为l1,r1,l2,r2. 则(l1-l2)*(r1-r2)<0时有交点。 通过上面的方法我们可以想到逆序数的解法。 先将所有直线根据l递增排序,之后编号1~n,再根据r递减排序,得到一个编号序列。例如3412,其中r3>r4>r1>r2, 又l1<l2<r3<r4,所以3和4有交点,1和2有交点。这符合逆序数的关系:一个数的逆序数是在它之前比他大的数的个数, 当然这里是小的数,原因是为了方便树状数组处理。所以只要根据上述方法排序再求逆序数即可。 不过有些特殊情况需要处理: 1.与y轴平行得线,只要这样的线在(l,r)范围内,则必定跟别的不平行线相交。所以计算下个数在乘积就OK。 2.l和r相同的情况。当l相同时,r递增排序;当r相同时,l递减排序。就能使在l和r上的交点不计算在内。 简要说下树状数组: 树状数组可以说是线段树的简化,处理单一,但写起来简便。详细的请百度。 两个函数: add(x,val),时c[x]+=val; sum(x),求c[1]+c[2]+...+c[x]; 特例: 4 0 1 0 4 1 3 0 3 1 4 0 3 1 2 0 2 1 3 */
相关文章推荐
- hdu 3465 Life is a Line 树状数组求逆序数
- HDU 3465 Life is a Line 树状数组求逆序数
- hdu 3465 Life is a Line(树状数组求逆序对)
- HDOJ 题目3465 Life is a Line(树状数组求逆序对)
- HDOJ 题目3465 Life is a Line(树状数组求逆序对,第二种写法)
- HDU 3465 Life is a Line 逆序数
- HDU 3465 Life is a Line (逆序数 + 数状数组)
- HDU3465--Life is a Line(树状数组求逆序数,离散化)
- HDU - 3465 Life is a Line
- hdu 3465 Life is a Line
- HDU - 3465 Life is a Line
- HDU 5792 World is Exploding(树状数组)
- HDU 2838 (树状数组求逆序数)
- HDU 2838 (树状数组求逆序数)
- HDU 5792 L - World is Exploding 。容斥原理 + 树状数组 + 离散化
- hdu 3743(树状数组求逆序数)
- HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)
- 【树状数组】hdu 4911 Inversion(离散化+树状数组求逆序数)
- HDU - 1394 Minimum Inversion Number 树状数组求逆序数
- HDU 4911 Inversion 树状数组求逆序数对