zoukankan      html  css  js  c++  java
  • 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)内的交点个数。成功将计算几何问题向树状数组转化。求逆序对数可用归并排序或者树状数组解决。

    代码:(树状数组)

    #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
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hdu 5007 水题 (2014西安网赛A题)
    hdu 1698 线段树(成段替换 区间求和)
    poj 3468 线段树 成段增减 区间求和
    hdu 2795 公告板 (单点最值)
    UVaLive 6833 Miscalculation (表达式计算)
    UVaLive 6832 Bit String Reordering (模拟)
    CodeForces 124C Prime Permutation (数论+贪心)
    SPOJ BALNUM (数位DP)
    CodeForces 628D Magic Numbers (数位DP)
    POJ 3252 Round Numbers (数位DP)
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3944694.html
Copyright © 2011-2022 走看看