HDU1542 矩形面积并 扫描线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542

题意:二维平面有n个平行于坐标轴的的矩形,要算矩形面积并

有一个讲的很好的博客:https://blog.csdn.net/u013480600/article/details/22548393

线段树是按叶节点来一个个维护的,一堆浮点数是不能直接维护的,需要离散化来维护。

要注意我们线段树中每个叶节点(控制区间[L,L])不是指X[L]坐标,而是指区间[X[L],X[L+1]].线段树中其他节点控制的区间[L,R],也是指的x坐标轴的第L个区间到第R个区间的范围,也就是X[L]到X[R+1]坐标的范围.

简而言之,维护的是区间。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
using namespace std;
typedef long long ll;
const int maxn=1000+10;
double dat[4*maxn];
int lazy[maxn];
double b[maxn];
struct edge{
    double l,r,h;
    int cnt;
    friend bool operator < (edge x,edge y){
        return x.h<y.h;
    }
}e[maxn];
void pushup(int a,int l,int r){
    if(lazy[a])    dat[a]=b[r+1]-b[l];
    else    dat[a]=dat[a<<1]+dat[a<<1|1];
}
void update(int a,int l,int r,int s,int t,int k){
    if(s>r || t<l)    return;
    if(s<=l && r<=t){
        lazy[a]+=k;
        pushup(a,l,r);
        return;
    }
    if(s<=mid)    update(a<<1,l,mid,s,t,k);
    if(t>mid)    update(a<<1|1,mid+1,r,s,t,k);
    pushup(a,l,r);
}
int main(){
    int n;
    int T=0;
    while(~scanf("%d",&n)){
        memset(dat,0,sizeof(dat));
        memset(lazy,0,sizeof(lazy));
        memset(b,0,sizeof(b));
        memset(e,0,sizeof(e));
        if(n==0)    return 0;
        T++;
        int p=0,num=0;
        for(int i=1;i<=n;i++){
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            e[++p].l=x1;
            e[p].r=x2;
            e[p].h=y1;
            e[p].cnt=1;
            e[++p].l=x1;
            e[p].r=x2;
            e[p].h=y2;
            e[p].cnt=-1;
            b[++num]=x1;
            b[++num]=x2;
        }
        sort(e+1,e+1+p);
        sort(b+1,b+1+num);
        int m=unique(b+1,b+1+num)-b-1;
        double ans=0;
        for(int i=1;i<p;i++){
            int l=lower_bound(b+1,b+m,e[i].l)-b;
            int r=lower_bound(b+1,b+m,e[i].r)-b;
            update(1,1,m-1,l,r-1,e[i].cnt);//记住r-1是关键,维护的是区间,一共有m-1个区间
            ans+=dat[1]*(e[i+1].h-e[i].h);
        }
        printf("Test case #%d\n",T);
        printf("Total explored area: %.2lf\n\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/qingjiuling/p/11330889.html

时间: 2024-11-06 09:32:11

HDU1542 矩形面积并 扫描线段树的相关文章

poj 1151 求矩形面积并 (线段树扫描线)

题意: 给出n个矩形的左下角和右上角坐标,求这n个矩形所构成的面积 思路: 线段树扫描线 这是第一次做到线段树扫描线,刚开始也不懂 如果不懂,可以看: http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html 和 http://www.faceye.net/search/69289.html 我是看第一个链接弄懂的 然后学习了第二位的方法 代码上也有比较详细的注释,想可以帮到大家 code: #include<cstd

【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)

[题目] Atlantis Problem 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 the island. But unfortunately, these maps describe different regions of

POJ1151Atlantis 矩形面积并 扫描线 线段树

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1151 题意概括 给出n个矩形,求他们的面积并. n<=100 题解 数据范围极小. 我们分3种算法逐步优化. 算法1: O(n3) 如果这n个矩形的坐标都是整数,而且比较小,那么我们显然可以用最暴力的方法:一个一个打标记. 但是不是这样的. 坐标大小很大,而且是实数. 然而我们发现差不多,只要先离散化一下,然后再打标记即可. 算法2:O(n2) 实际上,上面的方法十分慢.如果n的范围到了1000,

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

求出被矩形覆盖过至少两次的区域的面积(扫描线 + 线段树)

题目链接:https://vjudge.net/contest/332656#problem/J 思路: 这道题的大体的思路其实还是扫描线的思路. 就是我们要清晰之前我们所说的len 代表的是被覆盖了一次及以上次数的线段长度 为叙述方便,我们假设len[2]为当前线段被覆盖了两次的长度,len[1]为当前线段被覆盖了一次的长度,而len[0]就是这条线段的长度,并且满足len[2]+len[1]=len[0]. 首先,如果当前这条线段已经被覆盖了两次了,那么这条线段的len[2]就应该等于len

POJ 1389 Area of Simple Polygons(面积合并,线段树+离散化)

Area of Simple Polygons Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3257   Accepted: 1678 Description There are N, 1 <= N <= 1,000 rectangles in the 2-D xy-plane. The four sides of a rectangle are horizontal or vertical line segment

HDU1542矩形面积并

取出纵向边按x坐标排序,在y方向上建立线段树. 每次查询当前有效长度len,ans += len*(x[i]-x[i-1]); 其中len为T[rt].len; 查询完毕后更新y方向上线段树,入边+1, 出边-1. #include<bits/stdc++.h> using namespace std; #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 typedef long long ll; struct L

hdu1542矩阵的并(线段树+扫描线)

求矩阵的并,也就是要求所有的面积.那可以吧总的图形按照矩阵来切割.使其为一块一块. 输入的时候用坐标表示,这里扫描线从下到上扫描.初始时让下面的边为1,上面的为-1: 用一条先从下面开始想上扫描.遇到更新线段树,加入该条边,为-1时就除去改变. 这样从下到上一遍扫描就可以得到线段的长度.从下到上的过程中,一旦遇到一条边,那就计算他的高度. 高度*长度就是面积. /* 那叶子节点[l,l]的长度不就变成0,显然这是有问题的 线段树的每一个节点表示一段区间,[l,r]该区间表示LX[r+1]-LX[