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

总结

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

原文地址:https://www.cnblogs.com/31415926535x/p/9880243.html

时间: 2024-08-01 06:08:55

poj-1151矩形面积并-线段树的相关文章

POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线段树维护两个值:cover和len,cover表示该线段区间目前被覆盖的线段数目,len表示当前已覆盖的线段长度(化为离散前的真值),每次加入一条线段,将其y_low,y_high之间的区间染上line[i].cover,再以tree[1].len乘以接下来的线段的x坐标减去当前x坐标,即计算了一部

POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

POJ 2155 Matrix (二维线段树)

http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 18143   Accepted: 6813 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. I

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

HDU1255_覆盖的面积(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求面积交. 思路: 不会呀. 只知道线段树应该维护覆盖数大于2的线段长度. 不会更新,看了别人写的理解的,太菜了. 用sum1和sum2分别来表示覆盖数为1的区间长度和覆盖数为2的区间长度. 更新时即要更新sum1也要更新sum2: 区间如果被覆盖 sum1为实际区间长度,如果覆盖一次,sum2为左右子树的sum1和,覆盖两次就为实际区间长度. 没有被覆盖就直接等于左右子树的和. #include <algorithm> #include <iostream

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿

poj 3368 Frequent values(线段树解法)

题目链接:http://poj.org/problem?id=3368 题目大意:给你一段不下降的序列,求给定区间里出现次数最多的那个数字的次数. 思路:首先看到这题时,第一感觉线段树,但是仔细一看问题来啦,用线段数我怎么才能计算出某段区间里出现的那个数,因为出现最多的那个数可能不是在他它的左儿子上也不是在它的右儿子上,可能在当他们合并成一个区间时就出现啦,但是这儿我们需要注意的就是,题目给的是一段不下降的序列,那么突破口就出来啦,因为如果出现相同的数字,那么它们一定是连续的.所以我们只需要在普