avatar
fireworks99
keep hungry keep foolish

HDU 3642 Get The Treasury(Segment Tree Scanning Lines)

Description

长方体相交,求相交至少3次部分的体积

Analyze

相交至少三次与相交至少两次的处理方法一样

然后三维,降维做题,遍历Z轴,一层一层地求解

还有一点要注意,ans += len3[1] * (e[i + 1].h - e[i].h);不行了,相邻的两个面,e[i + 1]与e[i]只是y轴上相邻,Z轴上可能天上地下,所以用一个变量last记录本层前一个y

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20010;

int n;

int num;
int X[N];
int cnt[N << 2 | 1];
int len1[N << 2 | 1], len2[N << 2 | 1], len3[N << 2 | 1];

struct edge
{
    int l, r, h, zd, zu;
    int flag;
    edge(int a, int b, int c, int d, int f, int g):l(a), r(b), h(c), flag(d), zd(f), zu(g) {}
    edge() {}
    bool operator < (const edge & t)const
    {
        return h < t.h;
    }
} e[N];

void up(int o, int L, int R)
{
    if(cnt[o])
        len1[o] = X[R + 1] - X[L];
    else if(L == R)
        len1[o] = 0;
    else
        len1[o] = len1[o << 1] + len1[o << 1 | 1];

    if(cnt[o] >= 2)
        len2[o] = X[R + 1] - X[L];
    else if(L == R)
        len2[o] = 0;
    else
    {
        if(cnt[o] == 1)
            len2[o] = len1[o << 1] + len1[o << 1 | 1];
        else
            len2[o] = len2[o << 1] + len2[o << 1 | 1];
    }

    if(cnt[o] >= 3)
        len3[o] = X[R + 1] - X[L];
    else if(L == R)
        len3[o] = 0;
    else
    {
        if(cnt[o] == 2)
            len3[o] = len1[o << 1] + len1[o << 1 | 1];
        else if(cnt[o] == 1)
            len3[o] = len2[o << 1] + len2[o << 1 | 1];
        else
            len3[o] = len3[o << 1] + len3[o << 1 | 1];
    }
}

void update(int o, int L, int R, int l, int r, int val)
{
    if(L > r || R < l)
        return ;
    if(l <= L && R <= r)
    {
        cnt[o] += val;
        up(o, L, R);
        return ;
    }
    if(L == R)
        return ;

    int mid = (L + R) >> 1;
    update(o << 1, L, mid, l, r, val);
    update(o << 1 | 1, mid + 1, R, l, r, val);
    up(o, L, R);
}

int main()
{
    int _, t = 1;
    scanf("%d", &_);
    while(_--)
    {
        scanf("%d", &n);
        num = 0;
        int a, b, c, d, f, g;
        for(int i = 0; i < n; ++i)
        {
            scanf("%d %d %d %d %d %d", &a, &b, &f, &c, &d, &g);
            X[num] = a;
            e[num++] = edge(a, c, b, 1, f, g);
            X[num] = c;
            e[num++] = edge(a, c, d, -1, f, g);
        }

        sort(e, e + num);
        sort(X, X + num);
        int m = unique(X, X + num) - X;

        long long ans = 0;
        for(int z = -500; z <= 500; ++z)
        {
            memset(cnt, 0, sizeof(cnt));
            memset(len1, 0, sizeof(len1));
            memset(len2, 0, sizeof(len2));
            memset(len3, 0, sizeof(len3));
            int last = 0;
            for(int i = 0; i < num; ++i)
            {
                if(z >= e[i].zd && z < e[i].zu)
                {
                    int l = lower_bound(X, X + m, e[i].l) - X;///Segment Tree begins with 0
                    int r = lower_bound(X, X + m, e[i].r) - X - 1;
                    ans += (long long)len3[1] * (e[i].h - last);
                    update(1, 0, m - 2, l, r, e[i].flag);
                    last = e[i].h;
                }
            }
        }
        printf("Case %d: %lld\n", t++, ans);
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy