首页 > 其他 > 详细

扫描线

时间:2019-04-12 20:44:52      阅读:200      评论:0      收藏:0      [点我收藏+]

http://www.cnblogs.com/Konjakmoyu/p/6050343.html

关于扫描线的理解

 

https://vjudge.net/contest/242515#problem/F

 Atlantis

 HDU - 1542 

这个题目是求总的矩形覆盖面积。线段树中的点表示的是一段区间的长度。线段按照纵坐标由小到大来更新进线段树。

线段树的结构体中有个lazy标记与长度标记,lazy标记表示这个区间段被覆盖了几次,每次只要更新相对应区间的lazy值,不需要push_down 操作,然后push_up操作是来更新长度值,如果lazy标记为1,则表示该区间

有效,如果是叶子节点就是0,如果是0就表示不能确定,只能有其左右孩子的值来确定,(这里体现为什么不需要push_down操作,因为不一定要递归到叶子节点来找长度,可以直接拿一个已经标记了的区间来表示长度,如果标记为0表示没有被标记过或者先前的1被抵消掉了(在纸上画一下),那么就要通过子节点来得到长度。)

技术分享图片

#include<bits/stdc++.h>

using namespace std;

const int maxm = 105;
struct seg {
    double x1, x2, h;
    int fl;
//    seg(double x1 = 0, double x2 = 0, double h = 0, int fl = 0) : x1(x1), x2(x2), h(h), fl(fl) {};
    bool operator < (const struct seg &a) const {
        return h < a.h;
    }
}seg[maxm * 2];

struct Node {
    int l, r;
    int mid() {
        return (l + r) >> 1;
    }
}node[maxm << 3];
int lazy[maxm << 3];
double sum[maxm << 3];
double xx[maxm * 2];
int n;

void build(int ri, int l, int r) {
    node[ri].l = l;
    node[ri].r = r;
    lazy[ri] = 0;
    sum[ri] = 0;
    if(l == r) return;
    int m = node[ri].mid();
    build(ri << 1, l, m);
    build(ri << 1 | 1, m + 1, r);
}

void push_up(int ri) {
    if(lazy[ri]) {
        sum[ri] = xx[node[ri].r + 1] - xx[node[ri].l ];
        return;
    }
    if(node[ri].l == node[ri].r) {
        sum[ri] = 0;
        return;
    }
    sum[ri] = sum[ri << 1] + sum[ri << 1 | 1];
}

void update(int ri, int l, int r, int flag) {
    if(node[ri].l == l && node[ri].r == r) {
        lazy[ri] += flag;
        push_up(ri);
        return;
    }
    int m = node[ri].mid();
    if(r <= m) update(ri << 1, l, r, flag);
    else if(l > m) update(ri << 1 | 1, l, r, flag);
    else {
        update(ri << 1, l, m, flag);
        update(ri << 1 | 1, m + 1, r, flag);
    }
    push_up(ri);
}

int main() {
    double x1, x2, y1, y2;
    int ca = 0;
    while(~scanf("%d", &n) && n) {
        for(int i = 1; i <= n; i++) {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            seg[2 * i - 1] = (struct seg) {x1, x2, y1, 1};
            xx[2 * i - 1] = x1;
            seg[2 * i] = (struct seg) {x1, x2, y2, -1};
            xx[2 * i] = x2;
        }
        sort(seg + 1, seg + 2 * n + 1);
        sort(xx + 1, xx + 2 * n + 1);
        int k = unique(xx + 1, xx + 2 * n + 1) - xx;
        build(1, 1, k - 1);
        double res = 0;
        for(int i = 1; i < 2 * n; i++) {
            int l = lower_bound(xx + 1, xx + k, seg[i].x1) - xx;
            int r = lower_bound(xx + 1, xx + k, seg[i].x2) - xx - 1;
            if(l <= r) {
//                printf("nas\n");
                update(1, l, r, seg[i].fl);
            }
            res += sum[1] * (seg[i + 1].h - seg[i].h);
        }
//        for(int i = 1; i <= 3; i++) printf("%.2f\n", len[i]);
        printf("Test case #%d\nTotal explored area: %.2f\n\n", ++ca, res);
    }
    return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=1255

求覆盖两次的矩形面积。

https://blog.csdn.net/codeswarrior/article/details/81081692 跟覆盖一次的差不多,只是结构体中长度的变为一个至少覆盖一次与至少覆盖两次的长度。

 

http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=1082

求一个点最多是多少个矩形的交点,然后要如果一个y值有多条线,应该先让正直的先进去,然后再试负值的,保证最小。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MX = 2e4 + 5;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 0,10000,1

int MAX[MX << 2], col[MX << 2];

struct Que {
    int L, R, top, d;
    bool operator<(const Que &b)const {
        if(top == b.top) return d > b.d;
        return top < b.top;
    }
    Que(int _top = 0, int _L = 0, int _R = 0, int _d = 0) {
        L = _L; R = _R; top = _top; d = _d;
    }
} Q[MX];

void push_up(int rt) {
    MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1])+ col[rt];
}

//void push_down(int rt) {
//    if(col[rt]) {
//        col[rt << 1] += col[rt];
//        col[rt << 1 | 1] += col[rt];
//        MAX[rt << 1] += col[rt];
//        MAX[rt << 1 | 1] += col[rt];
//        col[rt] = 0;
//    }
//}

void update(int L, int R, int d, int l, int r, int rt) {
    if(L <= l && r <= R) {
        MAX[rt] += d;
        col[rt] += d;
        return;
    }

    int m = (l + r) >> 1;
//    push_down(rt);
    if(L <= m) update(L, R, d, lson);
    if(R > m) update(L, R, d, rson);
    push_up(rt);
}

int main() {
    int n;
    //freopen("input.txt", "r", stdin);
    while(~scanf("%d", &n)) {
        memset(MAX, 0, sizeof(MAX));
        memset(col, 0, sizeof(col));

        for(int i = 1; i <= n; i++) {
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &x2, &y1, &y2);
            Q[i] = Que(y1, x1, x2, 1);
            Q[i + n] = Que(y2, x1, x2, -1);
        }
        sort(Q + 1, Q + 1 + 2 * n);

        int ans = 0;
        for(int i = 1; i <= 2 * n; i++) {
            update(Q[i].L, Q[i].R, Q[i].d, root);
            ans = max(ans, MAX[1]);
        }
        printf("%d\n", ans);
    }
    return 0;
}

https://vjudge.net/contest/285943#status/xiayuyang/N/0/

 

扫描线

原文:https://www.cnblogs.com/downrainsun/p/10698391.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!