HDU1255 área cubierta (línea de escaneo para área)

Descripción

Dado un número de rectángulos en el plano, encuentre el área del área cubierta por estos rectángulos al menos dos veces.

Ideas

Es muy similar a simplemente encontrar el área, usando len para almacenar la duración del intervalo cubierto más de dos veces.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;
#define endl '\n'
typedef long long ll;

const int N = 3000;

struct snode {
    double x, y1, y2;
    int flag;
    
};

bool cmp(const snode &a, const snode &b) {
    return a.x < b.x;
}

struct tnode {
    double sum, l, r, len;
};

tnode st[N << 2];
snode seg[N];
double num[N];
int lazy[N << 2];

void pushup(int rt) {
    if(lazy[rt] > 0) {
        st[rt].sum = st[rt].r - st[rt].l;
        if(lazy[rt] > 1) st[rt].len = st[rt].sum;
        else st[rt].len = st[rt << 1].sum + st[rt << 1 | 1].sum;
    } else {
        st[rt].sum = st[rt << 1].sum + st[rt << 1 | 1].sum;
        st[rt].len = st[rt << 1].len + st[rt << 1 | 1].len;
    }

}

void update(double L, double R, int rt, int flag) {
    if(L == st[rt].l && R == st[rt].r) {
        lazy[rt] += flag;
        pushup(rt);
        return ;
    }
    if(st[rt << 1].r > L) //>而不是>=?不能等于,否则长度为0,会进入死循环。
        update(L, min(R, st[rt << 1].r), rt << 1, flag);
    if(st[rt << 1 | 1].l < R) 
        update(max(L, st[rt << 1 | 1].l), R, rt << 1 | 1, flag);
    pushup(rt);
}

void build(int lef, int rig, int rt) {
    if(rig - lef > 1) { //由于mid公用,所以>1就可以
        int mid = (lef + rig) / 2;
        st[rt].l = num[lef];
        st[rt].r = num[rig];
        build(lef, mid, rt << 1);
        build(mid, rig, rt << 1 | 1); //mid而不是mid+1?因为是线段,头尾需要相连,否则会少值
        pushup(rt);
    } else {
        st[rt].l = num[lef];
        st[rt].r = num[rig];
        st[rt].sum = 0;
        st[rt].len = 0;
    }
}


int main() {
    
    //ios::sync_with_stdio(false);
    int n;
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        if(!n) break;
        for(int i = 0; i < n; i++) {
            double x1, x2, y1, y2;
            scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
            seg[i].x = x1; seg[i].y1 = y1; seg[i].y2 = y2; 
            seg[i].flag = 1;
            seg[i + n].x = x2; seg[i + n].y1 = y1; seg[i + n].y2 = y2; 
            seg[i + n].flag = -1;

            num[i + 1] = y1;
            num[i + 1 + n] = y2;
        }
        sort(num + 1, num + 1 + (2 * n));
        sort(seg, seg + 2 * n, cmp);
        memset(lazy, 0, sizeof lazy);
        build(1, 2 * n, 1);
        double ans = 0;
        update(seg[0].y1, seg[0].y2, 1, seg[0].flag);
        for(int i = 1; i < 2 * n; i++) {
            ans += (seg[i].x - seg[i - 1].x) * st[1].len;
            //cout << st[1].len << endl;
            update(seg[i].y1, seg[i].y2, 1, seg[i].flag);
            //cout << seg[i].x << " " << seg[i].y1 << " " << seg[i].y2 << endl;
        }
        printf("%.2lf\n", ans);
        //printf("Total explored area: %.2lf\n\n", ans);
    }
}

Supongo que te gusta

Origin www.cnblogs.com/limil/p/12741560.html
Recomendado
Clasificación