Atlantis HDU - 1542 (扫描线,线段树)

扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫。如果我扫到的是下边,那么久用线段树在这个区间内加上1,表示这个区间现在是有的,等我扫描到上边的时候在加上-1,把之前的消掉,然后线段树维护区间内的长度,这里不是直接用下标维护,而是需要另一个数组来维护,每次记录我当前的下标在原本的图中的长度。

在update部分用一个点表示我这个点以后的一个长度为1的区间,然后这样算出来的sum[1]就是我现在线段树里包括的区间大小,然后用现在的区间大小去乘上这一部分的高度,然后每次相加,就可以了

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 305;
const int maxm = 305;
using namespace std;

int n, m, tol, T;
struct Node {
    double l, r, h;
    int f;
    bool operator <(Node a) const {
        return h < a.h;
    }
};
Node node[maxn];
double a[maxn];
double sum[maxn << 2];
int cnt[maxn << 2];

void init() {
    memset(sum, 0, sizeof sum);
    memset(cnt, 0, sizeof cnt);
}

void pushup(int left, int right, int root) {
    if(cnt[root] != 0)        sum[root] = a[right + 1] - a[left];
    else if(left == right)    sum[root] = 0;
    else    sum[root] = sum[root << 1] + sum[root << 1 | 1];
}

void update(int left, int right, int prel, int prer, int val, int root) {
    if(prel <= left && right <= prer) {
        cnt[root] += val;
        pushup(left, right, root);
        return ;
    }
    int mid = (left + right) >> 1;
    if(prel <= mid)    update(left, mid, prel, prer, val, root << 1);
    if(prer > mid)    update(mid+1, right, prel, prer, val, root << 1 | 1);
    pushup(left, right, root);
}

int main() {
    int cas = 1;
    while(scanf("%d", &n)== 1 && n) {
        init();
        double x1, y1, x2, y2;
        for(int i=1; i<=n; i++) {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            node[2*i-1].l = x1;
            node[2*i].l = x1;
            node[2*i-1].r = x2;
            node[2*i].r = x2;
            node[2*i-1].h = y1;
            node[2*i].h = y2;
            node[2*i-1].f = 1;
            node[2*i].f = -1;
            a[2*i-1] = x1;
            a[2*i] = x2;
        }
        n = 2*n;
        sort(node+1, node+1+n);
        sort(a+1, a+1+n);
        int nn = unique(a+1, a+1+n) - (a+1);
        double ans = 0;
        for(int i=1; i<n; i++) {
            int l = lower_bound(a+1, a+1+nn, node[i].l) - a;
            int r = lower_bound(a+1, a+1+nn, node[i].r) - a;
            update(1, nn, l, r-1, node[i].f, 1);
            ans += (node[i+1].h - node[i].h) * sum[1];
        }
        printf("Test case #%d\n", cas++);
        printf("Total explored area: %0.2f\n", ans);
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/H-Riven/p/9356322.html

时间: 2024-10-12 13:44:14

Atlantis HDU - 1542 (扫描线,线段树)的相关文章

Atlantis HDU - 1542(线段树+扫描线)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 23452    Accepted Submission(s): 9278 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

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

HDU 1542 Atlantics 线段树+离散化扫描

将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描 每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int MAX=200+10; 9 int flag[MAX&l

hdu 1542(线段树+扫描线 求矩形相交面积)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12059    Accepted Submission(s): 5083 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

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

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

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

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

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

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

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Jack knows that there is a great underground treasury in a secret region. And he has a special d