您的位置:首页 > 其它

线段树

2016-06-23 11:18 309 查看
                线段树

/**** **** **** **** **** ****

*    Function Name :         线段树

*    Description :               HDOJ 1542 Atlantis

*                                        用于表示区间线段

**** **** **** **** **** ****/
#include<cstdio>
#include<algorithm>
using namespace std;

typedef struct ITREE_NODE {

     ITREE_NODE * pLChild, * pRChild;

     double left, right;        
// 左端点,右端点

     double measure;          
// 测度

     int count;                    
// 覆盖计数器

     int lines;                      
// 独立线段数

     int lbound, rbound;     
// 覆盖左、右顶点的线段数目

}*PITREE_NODE;

inline void safe_add(int & v, int value) {

    v += value;

    if (v < 0) v = 0;

}

void itree_splite(const double * pList, PITREE_NODE pParent, const int iLeft, const int iRight) {

    if (iRight - iLeft <= 1) return;

    int iMid = (iLeft + iRight) >> 1;

    pParent -> pLChild = new ITREE_NODE;

    pParent -> pRChild = new ITREE_NODE;

    memset(pParent -> pLChild, 0, sizeof(ITREE_NODE));

    memset(pParent -> pRChild, 0, sizeof(ITREE_NODE));

    pParent -> pLChild -> left = pList[iLeft];

    pParent -> pLChild -> right = pList[iMid];

    pParent -> pRChild -> left = pList[iMid];

    pParent -> pRChild -> right = pList[iRight];

    itree_splite(pList, pParent -> pLChild, iLeft, iMid);

    itree_splite(pList, pParent -> pRChild, iMid, iRight);

}

PITREE_NODE itree_generate(const double * pList, const int iListCount) {

    PITREE_NODE pRoot = new ITREE_NODE;

    memset(pRoot, 0, sizeof(ITREE_NODE));

    pRoot -> left = pList[0];

    pRoot -> right = pList[iListCount - 1];

    itree_splite(pList, pRoot, 0, iListCount - 1);

    return pRoot;

}

void itree_destroy(PITREE_NODE pParent) {

    if (pParent == NULL) return;

    if (pParent -> pLChild) itree_destroy(pParent -> pLChild);

    if (pParent -> pRChild) itree_destroy(pParent -> pRChild);

    delete pParent;

}

inline void itree_measure(PITREE_NODE pNode) {

    if (pNode -> count > 0)

        pNode -> measure = pNode -> right - pNode -> left;

    else if (pNode -> pLChild && pNode -> pRChild)

        pNode -> measure = pNode -> pLChild -> measure + pNode -> pRChild -> measure;

    else

          pNode -> measure = 0;

}

inline void itree_lines(PITREE_NODE pNode) {

    if (pNode -> count > 0) {

        pNode -> lines = 1;

    } else if (pNode -> pLChild && pNode -> pRChild) {

        if (pNode -> pLChild -> rbound && pNode -> pRChild -> lbound) {

            pNode -> lines = pNode -> pLChild -> lines + pNode -> lines - 1;

        } else {

            pNode -> lines = pNode -> pLChild -> lines + pNode -> lines;

        }

    } else {

        pNode -> lines = 0;

    }

}

// 插入的时候value = 1, 删除的时候value = -1
void itree_update(PITREE_NODE pParent, const double left, const double right,

                  int value) {

    if (pParent -> left == left && pParent -> right == right) {

        safe_add(pParent -> count, value);

        safe_add(pParent -> lbound, value);

        safe_add(pParent -> rbound, value);

        itree_measure(pParent);

        itree_lines(pParent);

    } else {

        if (pParent -> pLChild -> right > left) {

            if (pParent -> pLChild -> right >= right) {

                itree_update(pParent -> pLChild, left, right, value);

            } else {

                itree_update(pParent -> pLChild, left,

                         pParent -> pLChild -> right, value);

                itree_update(pParent -> pRChild, pParent -> pRChild -> left,

                         right, value);

            }

        } else {

            itree_update(pParent -> pRChild, left, right, value);

        }

        itree_measure(pParent);

        itree_lines(pParent);

        if (left == pParent -> left) safe_add(pParent -> lbound, value);

          if (right == pParent -> right) {

            safe_add(pParent -> rbound, value);

        }

    }

}

void itree_insert(PITREE_NODE pParent, const double left, const double right) {itree_update(pParent, left, right, 1);}

void itree_delete(PITREE_NODE pParent, const double left, const double right) {itree_update(pParent, left, right, -1);}

struct EVENT {

     double x, y1, y2;

     int type;

};

bool cmp(const EVENT & a, const EVENT & b) 

{ return a.x < b.x;}

PITREE_NODE pRoot;

EVENT env[200];
double Y[200];
double tsize = 0.0;

int main() {

    double x1, x2, y1, y2;

    int i, n, n2, cas = 0;

    while (scanf("%d", & n) == 1 && n) {

        cas++;

        n2 = n << 1;

        for (i = 0; i < n2; i += 2) {

            scanf("%lf%lf%lf%lf", & x1, & y1, & x2, & y2);

            env[i].x = x1;

            env[i].y1 = y1;

            env[i].y2 = y2;

            env[i].type = 1;

            env[i + 1].x = x2;

            env[i + 1].y1 = y1;

            env[i + 1].y2 = y2;

            env[i + 1].type = -1;

            Y[i] = y1;

            Y[i + 1] = y2;

        }

        sort(env, env + n2, cmp);

        sort(Y, Y + n2);

        pRoot = itree_generate(Y, n2);

        for (i = 0; i < n2; ++i) {

            if (i > 0) tsize += pRoot -> measure * (env[i].x - env[i - 1].x);

            else tsize = 0.0;

            itree_update(pRoot, env[i].y1, env[i].y2, env[i].type);

        }

        itree_destroy(pRoot);

        printf("Test case #%d\nTotal explored area: %.2lf\n\n", cas, tsize);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树