ZOJ 3157 Weapon --计算几何+树状数组
题意:给一些直线,问这些直线在直线x=L,x=R之间有多少个交点。
讲解见此文:http://blog.sina.com.cn/s/blog_778e7c6e0100q64a.html
首先将直线分别跟x=L+eps,x=R-eps(防止出现相同纵坐标,故+-eps)求他们的交点,求的纵坐标为low,high,首先按low从大到小排序,一次赋予一个ind值,再按high从大到小排序,此时ind的逆序对数即为(L,R)内的交点个数。成功将计算几何问题向树状数组转化。求逆序对数可用归并排序或者树状数组解决。
代码:(树状数组)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #define eps 1e-5 using namespace std; #define N 10007 struct node { double x,y; }; struct Line { node a,b; int ind; double low,high; }line[N]; int c[N],n; int cmp(Line ka,Line kb) { return ka.low > kb.low; } int cmp2(Line ka,Line kb) { return ka.high > kb.high; } int lowbit(int x){ return x & (-x); } void modify(int x) { while(x <= n) c[x]++,x += lowbit(x); } int getsum(int x) { int res = 0; while(x > 0) res += c[x],x -= lowbit(x); return res; } int main() { int i,x,j; double L,R; while(scanf("%d",&n)!=EOF) { memset(c,0,sizeof(c)); for(i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y); scanf("%lf%lf",&L,&R); L += eps,R -= eps; for(i=1;i<=n;i++) { double k = (line[i].b.y-line[i].a.y)/(line[i].b.x-line[i].a.x); line[i].low = k*(L-line[i].a.x) + line[i].a.y; line[i].high = k*(R-line[i].a.x) + line[i].a.y; } sort(line+1,line+n+1,cmp); for(i=1;i<=n;i++) line[i].ind = i; sort(line+1,line+n+1,cmp2); int ans = 0; for(i=1;i<=n;i++) { modify(line[i].ind); ans += i - getsum(line[i].ind); } printf("%d\n",ans); } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com