• poj-1151矩形面积并-线段树



    title: poj-1151矩形面积并-线段树
    date: 2018-10-30 22:35:11
    tags:

    • acm
    • 刷题
      categoties:
    • ACM-线段树

    概述

    线段树问题里的另一个问题,,,矩形面积并,,,,

    之前看lazy更新时看到下面这个的讲解,,,一大堆文字还有一大堆的图,,,,当时果断跳过,,,

    今天花了一下午加一晚上的时间看了看这块知识,,,然后尝试自己写出代码,,,算是简单的了解一下这块,,,

    题意

    这道矩形面积并问题的大意是给很多个矩形,,矩形之间可能有交集,,,然后问你这一大片的图形面积是多少,,,,

    数据量不大,,看到有很多人是暴力过的,,,

    但是用线段树来当作练习题锻炼锻炼思维还是很好的QAQ

    思路

    一开始我是看这篇博客有关矩形面积并的知识,,,
    这篇博客讲解的思路很不错,,,一遍之后大致了解了整个解决问题的思路,,,,但是它没有相应的练习题以及代码,,,,我完全不知道该从哪里下手,,,线段树的具体如何实现一脸懵逼,,,,还有,,,一般这种题都是要将一个方向的坐标 离散化,,,,嗯,,又是这个东西,,,,更是一脸的懵逼,,,,

    然后看了这篇博客,,对着代码,,,然后顺着思路写出来了,,,

    主要的几点:

    • 前面两个博客的图很形象的把思路理了一遍,,,,就是枚举一个方向,,比如y方向,,然后,,将x方向的坐标离散化,,分成若干个 单位线段,,,,线段树维护这个单位线段,,,还是那个博客形象一些
    • 整个图形的面积可以分成若干个小的矩形,,,然后加起来就行,,,,

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    #define aaa  cout << x[r + 1] << "----" << x[l] << endl;
    const int maxn = 205;
    double x[maxn << 2];           //所有的x的数据
    //每一条线段
    struct segment
    {
        double y;
        double l;
        double r;
        int flag;       //1 or -1: 入边or出边
        segment(){}
        segment(double y, double l , double r , int flag):y(y) , l(l) , r(r) , flag(flag){}
        bool operator < (const segment &res)
        {
            return y < res.y;
        }
    }seg[maxn << 1];
    
    //线段树维护所有的单位线段(离散后的)
    struct node
    {
        int cov;
        double len;
    }node[maxn << 2];
    void pushdown(int rt , int l , int r)
    {
        if(node[rt].cov)
            node[rt].len = x[r + 1] - x[l];
        else if(l == r)
            node[rt].len = 0;
        else
            node[rt].len = node[rt << 1].len + node[rt << 1 | 1].len;
    }
    void update(int rt , int l , int r , int L , int R , int cov)
    {
        if(L <= l && r <= R)
        {
            node[rt].cov += cov;
            pushdown(rt , l , r);
            return;
        }
        int mid = (l + r) >> 1;
        if(L <= mid)    update(rt << 1 , l , mid , L , R , cov);
        if(R >  mid)    update(rt << 1 | 1 , mid + 1 , r , L , R , cov);
        //pushdown
        pushdown(rt , l , r);
        return;
    }
    
    int main()
    {
        int n;
        int q = 1;
        while(scanf("%d" , &n) && n)
        {
            memset(x , 0 , sizeof x);
    
            double x1 , y1 , x2 , y2;
            int count = 0;
            for(int i = 0; i < n; ++i)
            {
                scanf("%lf%lf%lf%lf" , &x1 , &y1 , &x2 , &y2);
                seg[count]=segment(y1 , x1 , x2 , 1);
                x[count++] = x1;
                seg[count]=segment(y2 , x1 , x2 , -1);
                //segment[i].y = y1;segment[i].l = x1;segment[i].r = x2;segment[i].flag = 1;
                //segment[i + 1].y = y2;segment[i + n].l = x1;segment[i + n].r = x2;segment[i + n].flag = -1;
    
                x[count++] = x2;
            }
            //离散
            sort(seg , seg + count);
            sort(x , x + count);
    
            int sz = unique(x , x + count) - x;
            double ans = 0;
            for(int i = 0; i < count; ++i)
            {
                int l = lower_bound(x , x + sz , seg[i].l) - x;
                int r = lower_bound(x , x + sz , seg[i].r) - x - 1;
                update(1 , 0 , sz , l , r , seg[i].flag);
                ans += node[1].len * (seg[i + 1].y - seg[i].y);
            }
            printf("Test case #%d
    Total explored area: %.2f
    
    ",q++,ans);
        }
    }
    
    

    总结

    算了,,,先鸽了,,,细节那天再补一下,,,,
    (loading,,,,)

    剑之所指,心之所向,身之所往!!!
  • 相关阅读:
    XNA中的中文输入(三)
    0.033秒的艺术 测试程序性能
    0.033秒的艺术 List.Sort以及快速排序
    从Demo到Engine(二) Render Queue Sort
    Bounding Volume Performance Test:AABB vs OBB vs Sphere
    0.033秒的艺术 Radix Sort
    从Demo到Engine(一) IRenderable
    0.033秒的艺术 for vs. foreach
    XNA中的中文输入(一)
    0.033秒的艺术 XNA数学库中的陷阱
  • 原文地址:https://www.cnblogs.com/31415926535x/p/9880243.html
Copyright © 2020-2023  润新知