zoukankan      html  css  js  c++  java
  • 线段树 hdu3642 Get The Treasury

    不得不说,这是一题很经典的体积并。。

    然而还是debug了2个多小时...


    首先思路:按z的大小排序。

    然后相当于扫描面一样,,从体积的最下方向上方扫描,遇到这个面

    就将相应的两条线增加到set中,或者从set中删除,然后再对set中的全部边,求一次面积并


    因为最后求出来的是至少有3个体积叠加的部分的体积。

    所以须要维护3个节点,然后push_up会略微啰嗦一点...


    刚開始在set插入线段和删除线段的时候。搞错了线段所在面的编号,。然后一直例子都过不去也是醉了...

    总的来说代码比較冗长须要足够细心才干敲对..

    #include<map>
    #include<set>
    #include<cmath>
    #include<stack>
    #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;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define root 1,rear-1,1
    
    int const MX = 4e3 + 5;
    
    struct Side {
        int z, x1, y1, x2, y2, d, id;
        bool operator<(const Side &b)const {
            if(z == b.z) return d < b.d;
            return z < b.z;
        }
        Side() {}
        Side(int _z, int _id, int _x1, int _y1, int _x2, int _y2, int _d) {
            z = _z; x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2; d = _d; id = _id;
        }
    } A[MX];
    
    struct Line {
        int y, x1, x2, d, id;
        bool operator<(const Line &b)const {
            if(y == b.y) {
                if(d == b.d) return id < b.id;
                return d < b.d;
            }
            return y < b.y;
        }
        Line() {}
        Line(int _y, int _id, int _d, int _x1, int _x2) {
            y = _y; x1 = _x1; x2 = _x2; d = _d; id = _id;
        }
    };
    
    int X[MX], rear;
    int S1[MX << 2], S2[MX << 2], S3[MX << 2], cnt[MX << 2];
    set<Line>work;
    
    int BS(int x) {
        int L = 1, R = rear, m;
        while(L <= R) {
            m = (L + R) >> 1;
            if(X[m] == x) return m;
            if(X[m] > x) R = m - 1;
            else L = m + 1;
        }
        return -1;
    }
    
    void push_up(int l, int r, int rt) {
        if(cnt[rt]) {
            S1[rt] = X[r + 1] - X[l];
            if(cnt[rt] == 1) {
                S2[rt] = S1[rt << 1] + S1[rt << 1 | 1];
                S3[rt] = S2[rt << 1] + S2[rt << 1 | 1];
            } else {
                S2[rt] = X[r + 1] - X[l];
                if(cnt[rt] == 2) {
                    S3[rt] = S1[rt << 1] + S1[rt << 1 | 1];
                } else {
                    S3[rt] = X[r + 1] - X[l];
                }
            }
        } else if(l == r) S1[rt] = S2[rt] = S3[rt] = 0;
        else {
            S1[rt] = S1[rt << 1] + S1[rt << 1 | 1];
            S2[rt] = S2[rt << 1] + S2[rt << 1 | 1];
            S3[rt] = S3[rt << 1] + S3[rt << 1 | 1];
        }
    }
    
    void update(int L, int R, int d, int l, int r, int rt) {
        if(L <= l && r <= R) {
            cnt[rt] += d;
            push_up(l, r, rt);
            return;
        }
    
        int m = (l + r) >> 1;
        if(L <= m) update(L, R, d, lson);
        if(R > m) update(L, R, d, rson);
        push_up(l, r, rt);
    }
    
    LL solve() {
        memset(S1, 0, sizeof(S1));
        memset(S2, 0, sizeof(S2));
        memset(cnt, 0, sizeof(cnt));
    
        LL ans = 0;
        int last = 0;
        for(set<Line>::iterator it = work.begin(); it != work.end(); it++) {
            ans += (LL)(it->y - last) * S3[1];
            update(BS(it->x1), BS(it->x2) - 1, it->d, root);
            last = it->y;
        }
        return ans;
    }
    
    int main() {
        //freopen("input.txt", "r", stdin);
        int T, n, ansk = 0;
        scanf("%d", &T);
        while(T--) {
            rear = 0;
            work.clear();
    
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                int x1, y1, z1, x2, y2, z2;
                scanf("%d%d%d%d%d%d", &x1, &y1, &z1, &x2, &y2, &z2);
                A[i] = Side(z1, i, x1, y1, x2, y2, 1);
                A[i + n] = Side(z2, i, x1, y1, x2, y2, -1);
                X[++rear] = x1; X[++rear] = x2;
            }
            sort(A + 1, A + 1 + 2 * n);
            sort(X + 1, X + 1 + rear);
            rear = unique(X + 1, X + 1 + rear) - X - 1;
    
            LL ans = 0;
            int last = 0;
            printf("Case %d: ", ++ansk);
            for(int i = 1; i <= 2 * n; i++) {
                ans += (LL)(A[i].z - last) * solve();
    
                if(A[i].d > 0) {
                    work.insert(Line(A[i].y1, A[i].id, 1, A[i].x1, A[i].x2));
                    work.insert(Line(A[i].y2, A[i].id, -1, A[i].x1, A[i].x2));
                } else {
                    work.erase(Line(A[i].y1, A[i].id, 1, A[i].x1, A[i].x2));
                    work.erase(Line(A[i].y2, A[i].id, -1, A[i].x1, A[i].x2));
                }
                last = A[i].z;
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    


  • 相关阅读:
    df
    浅谈C#垃圾回收
    eclipse+ADT 进行android应用签名详解
    Android Monkey工具参数意义
    Android Monkey(转载)
    清理Win7右键菜单里“发送到”选项
    Android中LOG机制详解(上)  
    关于微博内容中的短地址ShortURL
    Android中LOG机制详解(下)
    黑盒测试用例设计方法实践(判定表驱动法)
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6941017.html
Copyright © 2011-2022 走看看