码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-07-23 19:53:24      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:roo   void   efi   stack   ios   ctime   线段树   扫描   sig   

扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫。如果我扫到的是下边,那么久用线段树在这个区间内加上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;
}
View Code

 

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

标签:roo   void   efi   stack   ios   ctime   线段树   扫描   sig   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!