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


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

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

概述

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

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

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

题意

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

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

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

思路

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

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

主要的几点:

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

代码

#include 
#include 
#include 
#include 
#include 

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\nTotal explored area: %.2f\n\n",q++,ans);
    }
}

总结

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

你可能感兴趣的:(poj-1151矩形面积并-线段树)