POJ 3642 长方体体积并 线段树 扫描线

来源:互联网 发布:qzj网络用语 编辑:程序博客网 时间:2024/06/02 14:37

这题就是给出了好多个长方体, 求出那些被覆盖了 3次及以上的体积


我们注意到z的范围很小,而且就给了1000个长方体

那么可以把z坐标离散化

然后在相邻的z坐标空间内,就变成了求面积覆盖

记录三个变量,代表一次覆盖,两次覆盖,三次覆盖及以上

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-5#define MAXN 2222#define MAXM 5555#define INF 100000007#define lch(x) x<<1#define rch(x) x<<1|1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;struct Seg{    int l, r, h;    int s;    Seg(){}    Seg(int a, int b, int c, int d){l = a; r = b; h = c; s = d;}    bool operator <(const Seg &cmp)const    {        if(cmp.h == h) return s > cmp.s;        return h < cmp.h;    }}seg[MAXN];struct Spot{    int lx, rx, ly, ry, lz, rz;}p[MAXN];int x[MAXN], z[MAXN];int sum[4 * MAXN], sum2[4 * MAXN], sum3[4 * MAXN], cnt[4 * MAXN];int bin(int low, int high, int v){    while(low <= high)    {        int mid = (low + high) >> 1;        if(x[mid] == v) return mid;        else if(x[mid] > v) high = mid - 1;        else low = mid + 1;    }    return -1;}void up(int rt, int l, int r){    if(cnt[rt] >= 3) sum[rt] = sum2[rt] = 0, sum3[rt] = x[r + 1] - x[l];    else if(cnt[rt] == 2)    {        if(l == r) sum2[rt] = x[r + 1] - x[l], sum3[rt] = 0, sum[rt] = 0;        else        {            sum3[rt] = sum[lch(rt)] + sum[rch(rt)] + sum2[lch(rt)] + sum2[rch(rt)] + sum3[lch(rt)] + sum3[rch(rt)];            sum2[rt] = x[r + 1] - x[l] - sum3[rt];            sum[rt] = 0;        }    }    else if(cnt[rt] == 1)    {        if(l == r) sum[rt] = x[r + 1] - x[l], sum2[rt] = 0, sum3[rt] = 0;        else        {            sum3[rt] = sum2[lch(rt)] + sum2[rch(rt)] + sum3[lch(rt)] + sum3[rch(rt)];            sum2[rt] = sum[lch(rt)] + sum[rch(rt)];            sum[rt] = x[r + 1] - x[l] - sum2[rt] - sum3[rt];        }    }    else    {        if(l == r) sum[rt] = sum2[rt] = sum3[rt] = 0;        else        {            sum3[rt] = sum3[lch(rt)] + sum3[rch(rt)];            sum2[rt] = sum2[lch(rt)] + sum2[rch(rt)];            sum[rt] = sum[lch(rt)] + sum[rch(rt)];        }    }}void update(int L, int R, int v, int l, int r, int rt){    if(L <= l && R >= r)    {        cnt[rt] += v;        up(rt, l, r);        return;    }    int m = (l + r) >> 1;    if(L <= m) update(L, R, v, lson);    if(R > m) update(L, R, v, rson);    up(rt, l, r);}int main(){    int T, n, cas = 0;    scanf("%d", &T);    while(T--)    {        scanf("%d", &n);        int m = 0;        for(int i = 1; i <= n; i++)        {            scanf("%d%d%d%d%d%d", &p[i].lx, &p[i].ly, &p[i].lz, &p[i].rx, &p[i].ry, &p[i].rz);            z[m++] = p[i].lz;            z[m++] = p[i].rz;        }        sort(z, z + m);        int km = unique(z, z + m) - z;        long long ans = 0;        for(int i = 0; i < km - 1; i++)        {            memset(sum, 0, sizeof(sum));            memset(sum2, 0, sizeof(sum2));            memset(sum3, 0, sizeof(sum3));            memset(cnt, 0, sizeof(cnt));            m = 0;            for(int j = 1; j <= n; j++)                if(p[j].lz <= z[i] && p[j].rz > z[i])                {                    x[m] = p[j].lx;                    seg[m++] = Seg(p[j].lx, p[j].rx, p[j].ly, 1);                    x[m] = p[j].rx;                    seg[m++] = Seg(p[j].lx, p[j].rx, p[j].ry, -1);                }            sort(x, x + m);            sort(seg, seg + m);            int kx = unique(x, x + m) - x;            for(int j = 0; j < m - 1; j++)            {                int l = bin(0, kx - 1, seg[j].l);                int r = bin(0, kx - 1, seg[j].r) - 1;                if(l <= r) update(l, r, seg[j].s, 0, kx - 1, 1);                ans += (long long)sum3[1] * (long long)(seg[j + 1].h - seg[j].h) * (long long)(z[i + 1] - z[i]);            }        }        printf("Case %d: %I64d\n", ++cas, ans);    }    return 0;}


原创粉丝点击