Picture POJ - 1177(扫描线 + 线段树)

题意:求矩形并的面积。。

解析:

  扫描线第一道题。。。。自下而上扫描的。。。

如果不懂什么是扫描线戳我

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_wity_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 201, INF = 0x7fffffff;
double X[maxn];  //记录x的坐标

struct node{
    int l, r;  // 线段树的左右端点
    int w;     // 记录边重叠的情况
    double lx, rx, sum; //sum代表当前区间线段的长度,lx和rx为线段的真实端点

}Node[maxn*4];

struct edge{
    double lxx, rxx, y; // 存储边的左右端点和y
    int f;    //标记是下边还是上边 (下边为-1 上边为1)
}Edge[maxn];

int cmp(edge a, edge b)
{
    return a.y < b.y;    // 按y从小到大排序  把线段的高度从低到高排序
}

void build(int k, int ll, int rr) //建树
{
    Node[k].l = ll, Node[k].r = rr;
    Node[k].sum = Node[k].w = 0;
    Node[k].lx = X[ll];
    Node[k].rx = X[rr];
    if(ll + 1 == rr) return;
    int m = (ll + rr) / 2;
    build(k*2, ll, m);
    build(k*2+1, m, rr);
}

void down(int k)  //计算长度
{
    if(Node[k].w > 0)
    {
        Node[k].sum = Node[k].rx - Node[k].lx;
        return;
    }
    if(Node[k].l + 1 == Node[k].r) Node[k].sum = 0;
    else
    {
        Node[k].sum = Node[k*2].sum + Node[k*2+1].sum;
    }
}

void update(int k, edge e)  // 更新
{
    if(Node[k].lx == e.lxx && Node[k].rx == e.rxx)
    {
        Node[k].w += e.f;
        down(k);
        return;
    }
    if(e.rxx <= Node[k*2].rx) update(k*2, e);
    else if(e.lxx >= Node[k*2+1].lx) update(k*2+1, e);
    else
    {
        edge g = e;
        g.rxx = Node[k*2].rx;
        update(k*2, g);
        g = e;
        g.lxx = Node[k*2+1].lx;
        update(k*2+1, g);

    }
    down(k);
}
int main()
{
    int n, cnt, kase = 0;
    while(~scanf("%d",&n) && n)
    {
        cnt = 0;
        for(int i=0; i<n; i++)
        {
            double x1, y1, x2, y2;
            scanf("%lf%lf%lf%lf",&x1, &y1, &x2, &y2);
            Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y1, Edge[cnt].f = 1;
            X[cnt] = x1;
            Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y2, Edge[cnt].f = -1;
            X[cnt] = x2;
        }
        sort(Edge+1, Edge+cnt+1, cmp);
        sort(X+1, X+cnt+1);
        build(1, 1, cnt);
        double ret = 0;
        for(int i=1; i<cnt; i++)
        {
            update(1, Edge[i]);
            ret += (Edge[i+1].y - Edge[i].y) * Node[1].sum;
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",++kase,ret);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/WTSRUVF/p/9251282.html

时间: 2024-12-21 19:22:34

Picture POJ - 1177(扫描线 + 线段树)的相关文章

POJ 1177:线段树 离散化 扫描线

计算畸形区域的周长 比面积的扫描要麻烦些,原因就在不重叠区域的处理,同一段高度可能要重复叠加 所以线段树的结点里要多维护三个东西: times:区间里不重叠的区间数 比如说第一个区间是1~5,第二个是2~6,,第三个是9~10,那前两个可以合成1~6,和第三个独立,则这个整体的times为2 为了维护times,我们需要lbd和rbd两个变量,分别作为区间左右端点是否被覆盖的标志 有的博客里把这两个变量写成了bool型,这些其实不好,在运算时会带来麻烦,我们直接用int 0和1表示会好些.这样只

POJ 1151 扫描线 线段树

题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离散化之后线段树的第i个叶子节点储存的是y[i+1]-y[i]. 这里的线段树用的是一个不用下传延迟标记的做法(仅限这一类题).线段树的每一个节点维护length(这个节点的子节点覆盖的长度)和cnt(这个节点代表的线段[l,r]所覆盖的次数). 任意一个区间都可以被线段树划分成O(logn)个子区间,我们

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,就是给出图形中间的小矩

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

poj 1151 Atlantis (离散化 + 扫描线 + 线段树)

题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt

HNU12884_Area Coverage(扫描线/线段树+离散化)

解题报告 题目传送门 题意: 又是求面积并 思路: 又是求面积并,还被坑了,题目明明描述的是int坐标,用了double才过... #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { double lx,rx,h; int v; friend bool operator <(Seg

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l

POJ 2481 Cows (线段树)

Cows 题目:http://poj.org/problem?id=2481 题意:有N头牛,每只牛有一个值[S,E],如果对于牛i和牛j来说,它们的值满足下面的条件则证明牛i比牛j强壮:Si <=Sjand Ej <= Ei and Ei - Si > Ej - Sj.现在已知每一头牛的测验值,要求输出每头牛有几头牛比其强壮. 思路:将牛按照S从小到大排序,S相同按照E从大到小排序,这就保证了排在后面的牛一定不比前面的牛强壮.再按照E值(离散化后)建立一颗线段树(这里最值只有1e5,所

POJ 2299 离散化线段树

点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 40827   Accepted: 14752 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by