线段树 扫描线 L

学习博客推荐——线段树+扫描线(有关扫描线的理解)

 我觉得要注意的几点

1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1]

2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个push_down

3 注意push_up 写法有点不一样,不过是可以改成一样的。

简单裸题*2

L - Atlantis  HDU - 1542 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 220;
double v[maxn];
struct node {
    double l, r, h;
    int d;
    node(double l = 0, double r = 0, double h = 0, int d = 0) :l(l), r(r), h(h), d(d) {}
}line[maxn];
bool cmp(node a, node b) {
    return a.h < b.h;
}
double sum[maxn * 8];
int lazy[maxn * 4];
void build(int id, int l, int r) {
    sum[id] = 0;
    lazy[id] = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
}

void push_up(int id, int l, int r) {
    if (lazy[id]) sum[id] = v[r + 1] - v[l];
    else sum[id] = sum[id << 1] + sum[id << 1 | 1];
}

void update(int id, int l, int r, int x, int y, int d) {
    if (x <= l && y >= r) {
        lazy[id] += d;
        push_up(id, l, r);
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) update(id << 1, l, mid, x, y, d);
    if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d);
    push_up(id, l, r);
}

int main() {
    int n, cas = 0;
    while (scanf("%d", &n) != EOF && n) {
        int cnt = 0, tot = 0;
        for (int i = 1; i <= n; i++) {
            double x1, y1, x2, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            v[++cnt] = x1, v[++cnt] = x2;
            line[++tot] = node(x1, x2, y1, 1), line[++tot] = node(x1, x2, y2, -1);
        }
        sort(v + 1, v + 1 + cnt);
        sort(line + 1, line + 1 + tot, cmp);
        int len = unique(v + 1, v + 1 + cnt) - v - 1;
        double ans = 0;
        build(1, 1, len - 1);
        for (int i = 1; i < tot; i++)//这里注意只需要要tot-1即可,因为我们每次都是按底算的
        {
            int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v;
            int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1;
            update(1, 1, len - 1, l, r, line[i].d);
            ans += sum[1] * (line[i + 1].h - line[i].h);
        }
        printf("Test case #%d
", ++cas);
        printf("Total explored area: %.2lf

", ans);
    }
    return 0;
}
View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 8e4 + 10;
ll v[maxn];
struct node {
    ll l, r, h;
    int d;
    node(ll l = 0, ll r = 0, ll h = 0, int d = 0) :l(l), r(r), h(h), d(d) {}
}line[maxn];
bool cmp(node a, node b) {
    return a.h < b.h;
}
ll sum[maxn * 8];
int lazy[maxn * 4];
void build(int id, int l, int r) {
    sum[id] = 0;
    lazy[id] = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
}

void push_up(int id, int l, int r) {
    if (lazy[id]) sum[id] = v[r + 1] - v[l];
    else sum[id] = sum[id << 1] + sum[id << 1 | 1];
}

void update(int id, int l, int r, int x, int y, int d) {
    if (y<l || x>r) return;
    // printf("id=%d l=%d r=%d x=%d y=%d
", id, l, r, x, y);
    if (x <= l && y >= r) {
        lazy[id] += d;
        if (lazy[id]) sum[id] = v[r + 1] - v[l];
        else sum[id] = sum[id << 1] + sum[id << 1 | 1];
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) update(id << 1, l, mid, x, y, d);
    if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d);
    push_up(id, l, r);
}

int main() {
    int n, cnt = 0, tot = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        ll l, r, h;
        scanf("%lld%lld%lld", &l, &r, &h);
        v[++cnt] = l, v[++cnt] = r;
        line[++tot] = node(l, r, 0, 1), line[++tot] = node(l, r, h, -1);
    }
    sort(v + 1, v + 1 + cnt);
    sort(line + 1, line + 1 + tot, cmp);
    int len = unique(v + 1, v + 1 + cnt) - v - 1;
    build(1, 1, len - 1);
    ll ans = 0;
    for (int i = 1; i < tot; i++) {
        int l = lower_bound(v + 1, v + 1 + len, line[i].l) - v;
        int r = lower_bound(v + 1, v + 1 + len, line[i].r) - v - 1;
        // printf("l=%d r=%d
", l, r);
        update(1, 1, len - 1, l, r, line[i].d);
        ans += sum[1] * (line[i + 1].h - line[i].h);
        // printf("%lld %lld ans=%lld %lld sum=%lld
", line[i].l, line[i].r, ans, line[i].h, sum[1]);
        // printf("%lld %lld ans=%lld %lld
", line[i + 1].l, line[i + 1].r, ans, line[i + 1].h);
        // printf("

");
    }
    printf("%lld
", ans);
    return 0;
}
View Code
然后就是一个没有这么简单的裸题,比较暴力。
这个是给每一个y轴都建一棵线段树,每一个y轴代表 y[L]~y[L+1]

然后每次对于这个矩形的每一个y轴的这一段都查一下,然后如果已经被覆盖了,就删去这一段,然后更新这一段。

这个题目其实还是很好写的,但是要注意push_down的写法。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 440;
struct rect
{
    int x1, y1, x2, y2, col;
    rect(int x1=0,int y1=0,int x2=0,int y2=0,int col=0):x1(x1),y1(y1),x2(x2),y2(y2),col(col){}
}ex[maxn];

int vx[maxn * 2], vy[maxn * 2], color[maxn];
int sum[maxn][maxn * 8], lazy[maxn][maxn * 8];

void build(int i,int id,int l,int r)
{
    sum[i][id] = lazy[i][id] = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build( i,id << 1, l, mid);
    build(i, id << 1 | 1, mid + 1, r);
}

void push_up(int i,int id)
{
    sum[i][id] = sum[i][id << 1] + sum[i][id << 1 | 1];
    // printf("sum[%d][%d]=%d
", i, id, sum[i][id]);
}

void push_down(int i,int id,int l,int r)
{
    if (lazy[i][id] == 0) return;
    int mid = (l + r) >> 1;
    sum[i][id << 1] = vx[mid + 1] - vx[l];
    sum[i][id << 1 | 1] = vx[r + 1] - vx[mid + 1];
    lazy[i][id << 1] = lazy[i][id << 1 | 1] = lazy[i][id];
    // printf("l=%d r=%d mid=%d
", l, r, mid);
    // printf("x sum[%d][%d]=%d
", i, id<<1, sum[i][id<<1]);
    // printf("x sum[%d][%d]=%d
", i, id<<1|1, sum[i][id<<1|1]);
    lazy[i][id] = 0;
}

void update(int i,int id,int l,int r,int x,int y)
{
    if (x <= l && y >= r) {
        sum[i][id] = vx[r + 1] - vx[l];
        // printf("l=%d r=%d
", l, r);
        // printf("ww sum[%d][%d]=%d
", i, id, sum[i][id]);
        lazy[i][id] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    push_down(i, id, l, r);
    if (x <= mid) update(i, id << 1, l, mid, x, y);
    if (y > mid) update(i, id << 1 | 1, mid + 1, r, x, y);
    push_up(i, id);
}

int query(int i,int id,int l,int r,int x,int y)
{
    if (x <= l && y >= r) return sum[i][id];
    int mid = (l + r) >> 1, ans = 0;
    push_down(i, id, l, r);
    if (x <= mid) ans += query(i, id << 1, l, mid, x, y);
    if (y > mid) ans += query(i, id << 1 | 1, mid + 1, r, x, y);
    return ans;
}

int main()
{
    int w, h, n, cas = 0;
    while (scanf("%d%d", &w, &h) && (w + h)) {
        memset(color, 0, sizeof(color));
        int tot = 0, cnt = 0;
        scanf("%d", &n);
        vx[++tot] = 0, vx[++tot] = w;
        vy[++cnt] = 0, vy[++cnt] = h;
        for (int i = 1; i <= n; i++) {
            int x1, y1, x2, y2, col;
            scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &col);
            ex[i] = rect(x1, y1, x2, y2, col);
            vx[++tot] = x1, vx[++tot] = x2;
            vy[++cnt] = y1, vy[++cnt] = y2;
        }
        sort(vx + 1, vx + 1 + tot);
        sort(vy + 1, vy + 1 + cnt);
        int lenx = unique(vx + 1, vx + 1 + tot) - vx - 1;
        int leny = unique(vy + 1, vy + 1 + cnt) - vy - 1;
        // for (int i = 1; i <= lenx; i++) printf("vx[%d]=%d
", i, vx[i]);
        for (int i = 1; i < leny; i++) build(i, 1, 1, lenx - 1);
        for (int i = n; i >= 1; i--) {
            // printf("i=%d
", i);
            int col = ex[i].col;
            int ans = (ex[i].x2 - ex[i].x1)*(ex[i].y2 - ex[i].y1);
            int lx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x1) - vx;
            int ly = lower_bound(vy + 1, vy + 1 + leny, ex[i].y1) - vy;
            int rx = lower_bound(vx + 1, vx + 1 + lenx, ex[i].x2) - vx - 1;
            int ry = lower_bound(vy + 1, vy + 1 + leny, ex[i].y2) - vy - 1;
            for (int j = ly; j <= ry; j++) {
                int res = query(j, 1, 1, lenx - 1, lx, rx);
                ans -= (vy[j + 1] - vy[j])*res;
                // printf("j=%d
", j);
                // printf("lx=%d ly=%d rx=%d  ry=%d
", lx, ly, rx, ry);
                // printf("x1=%d y1=%d x2=%d y2=%d
", ex[i].x1, ex[i].y1, ex[i].x2, ex[i].y2);
                // printf("res=%d %d ans=%d
", res, vy[j + 1] - vy[j],ans);
                update(j, 1, 1, lenx - 1, lx, rx);
            }
            color[col] += ans;
            // printf("color[%d]=%d
", col, color[col]);
            // printf("
");
        }
        int num = 0;
        if (cas) printf("
");
        printf("Case %d:
", ++cas);
        for (int i = 1; i <= 100; i++) {
            if (color[i]) {
                printf("%d %d
", i, color[i]);
                num++;
            }
        }
        if (num == 1) printf("There is %d color left on the wall.
", num);
        else printf("There are %d colors left on the wall.
", num);
    }
    return 0;
}
/*
10 8
4
1 9 5 10 9
1 8 2 9 8
7 1 10 8 4
6 2 9 6 4
0 0

 */
View Code
原文地址:https://www.cnblogs.com/EchoZQN/p/11378192.html