• 扫描线 hdu1542


    扫描线分类两种,一种离散y轴,一种离散x轴。以离垂直x轴的直线为例:

    将每个离散的线之间作为一个线段树的叶子节点,然后从最小与x轴平行的直线开始,区覆盖线段树的叶子节点,

    也就是两根与y轴平行的直线之间所夹的空间,这段空间的长度乘以你的扫描线之间的距离(与x轴平行的直线),就是面积,

    看图吧,图下的数字是代表覆盖的次数,矩形的下底线扫描覆盖节点时为 value +=1,上边线扫描 value -= 1;

    代码如下

    #include <map>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    const int maxn = 205;
    
    struct node
    {
        int r, l, lazy;
        double dat;
    }tr[maxn<<2];
    
    struct bian
    {
        double x, a, b;
        int k;
    }egde[maxn<<1];
    
    int n;
    double yy[maxn << 1];
    map<double, int> mp;
    
    //注意节点为 l+1=r,离散化会丢失离散节点之间的信息
    void build(int p, int l, int r)
    {
        tr[p].dat = 0;
        tr[p].l = l;tr[p].r = r;
        tr[p].lazy = 0;
        if (l == r - 1)return;
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid, r);
    }
    
    inline void push(int p)
    {
        if (tr[p].lazy)tr[p].dat = yy[tr[p].r] - yy[tr[p].l];
        else if (tr[p].l + 1 == tr[p].r)tr[p].dat = 0;
        else tr[p].dat = tr[p << 1].dat + tr[p << 1 | 1].dat;
    }
    
    void updata(int p, int l, int r, int k)
    {
        if (tr[p].l > r || tr[p].r < l) return;
        if (l <= tr[p].l && tr[p].r <= r)
        {
            tr[p].lazy += k;
            push(p);
            return;
        }
        int mid = (tr[p].l + tr[p].r) >> 1;
        if (l <= mid) updata(p << 1, l, r, k);
        if (mid < r) updata(p << 1 | 1, l, r, k);
        push(p);
    }
    
    bool cmp(const bian& a, const bian& b)
    {
        if(a.x != b.x)return a.x < b.x;
        return a.k > b.k;
    }
    
    int main(void)
    {
        /*freopen("atlantis.in", "r", stdin);
        freopen("atlantis.out", "w", stdout);*/
        for (int cas = 1;~scanf("%d", &n)&&n; ++cas)
        {
            double ans = 0;
            for (int i = 0; i < n; ++i)
            {
                double x, y, a, b;
                scanf("%lf%lf%lf%lf", &x, &y, &a, &b);
                egde[i << 1] = { x, y, b, 1 };
                egde[i << 1 | 1] = { a, y, b, -1 };
                yy[i << 1] = y;yy[i << 1 | 1] = b;
            }
            sort(yy, yy + (n << 1));sort(egde, egde + (n << 1), cmp);
            int tot = unique(yy, yy + (n << 1)) - yy;
            for (int i = 0; i < tot; ++i)mp[yy[i]] = i;
            build(1, 0, tot - 1);
            updata(1, mp[egde[0].a], mp[egde[0].b], egde[0].k);
            for (int i = 1; i < (n << 1); ++i)
            {
                ans += (egde[i].x - egde[i - 1].x) * tr[1].dat;
                updata(1, mp[egde[i].a], mp[egde[i].b], egde[i].k);
            }
            printf("Test case #%d
    Total explored area: %.2lf
    
    ", cas, ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    在多个游戏视图间切换实现效果
    Animator窗口视图Project视图PlayerIdleAnimation和PlayerWalkingAnimation
    Swift 1.1语言函数参数的特殊情况本地参数名外部参数名
    Delphi-网络编程-UDP聊天程序(转)
    Delphi 编程进阶
    Android自定义控件(状态提示图表) (转)
    74HC166与TPIC6A595分析(转)
    基于STM32的USB枚举过程学习笔记
    USB那点事3 -使用端口2作为custom HID的传输(转)
    STM32-USB那点事
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12153873.html
Copyright © 2020-2023  润新知