矩形树

对于多维的问题,第一种方法几乎不可能使用。因此我们可以仿照第二种方法。例如对于n维的问题。我们构造以(a1,a2,a3,….,an,b1,b2,b3,….,bn)为根的线段树,其中(a1,a2,a3….,an)表示的是左下角的坐标,(b1,b2,b3,….,bn)表示的是右上角的坐标。构造的时候用的就不是二分,四分了,而是2n分,构造出一棵2n叉树。结点的个数变为2n×(b1-a1)×(b2-a2)×………×(bn-an)

 

以上转载自xuemao大牛的论文

 

const int maxn = 1000*1000*1.5;

//2D line tree

struct node

{

    short x1,y1,x2,y2;    //(a,b)--(c,d)    

    float max;

    int *ch;

};

 

node tree[maxn];  //空间:O(N*M * 2)  //实际上,1.4*N*M就足够了

 

int tol;

 

void maketree(int x1,int y1,int x2,int y2)  //时间:O(2*N*M) 空间:O(2*N*M)

{

    tol++;

    int k = tol;

    tree[k].x1 = x1;

    tree[k].y1 = y1;

    tree[k].x2 = x2;

    tree[k].y2 = y2;

    tree[k].max = 0.0;

 

    if(x1==x2 && y1 == y2) //c==d

    {

        tree[k].ch = 0;

        return;

    }

 

    tree[k].ch = new int[4];

 

    int midx = (x1+x2)/2;

    int midy = (y1+y2)/2;

 

    if(x1<=midx && y1 <= midy)  //左下

    {

        tree[k].ch[0] = tol+1;

        maketree(x1,y1,midx,midy);

    }

    else

        tree[k].ch[0] = 0;

 

    if(midx+1 <= x2 && midy+1 <= y2)  //右上

    {

        tree[k].ch[1] = tol+1;

        maketree(midx+1,midy+1,x2,y2);

    }

    else

        tree[k].ch[1] = 0;

   

    if(x1 <= midx && midy+1 <= y2)  //左上

    {

        tree[k].ch[2] = tol+1;

 

        maketree(x1,midy+1,midx,y2);   

    }

    else

        tree[k].ch[2] = 0;

 

    if(midx+1 <= x2 && y1 <= midy) //右下

    {

        tree[k].ch[3] = tol+1;

        maketree(midx+1,y1,x2,midy);

    }

    else

        tree[k].ch[3] = 0;

}

 

//时间:O(logN)//N*N的矩形

void insert(int x,int y,int L,int k) //这里,针对插入的是一个矩形[x,y]--[x,y]..一个单位正方形

{

    if(tree[k].x1 == tree[k].x2 && tree[k].y1 == tree[k].y2) //叶子结点  //

    {

        if(L > tree[k].max)

            tree[k].max = L;

        return;

    }

 

    int midx = (tree[k].x1+tree[k].x2)/2;

    int midy = (tree[k].y1+tree[k].y2)/2;

 

    if(x<=midx)

    {

        if(y<=midy)

            insert(x,y,L,tree[k].ch[0]);

        else

            insert(x,y,L,tree[k].ch[2]);

    }

    else  //x>midx

    {

        if(y<=midy)

            insert(x,y,L,tree[k].ch[3]);

        else

            insert(x,y,L,tree[k].ch[1]);

    }

   

    float m = tree[tree[k].ch[0]].max;

 

    for(int i=1; i<4; i++)

        m = max(m,tree[tree[k].ch[i]].max);

 

    tree[k].max = m;

}

 

 

inline bool corss(int x1,int y1,int x2,int y2,int k) //判断两矩形是否相交

{

    int x3 = tree[k].x1;

    int y3 = tree[k].y1;

    int x4 = tree[k].x2;

    int y4 = tree[k].y2;

 

    if(y2 < y3 || y4 < y1 || x4 < x1 || x2 < x3)

        return false;

    else

        return true;

}

 

//时间:O(logN)//N*N的矩形

float Query(int x1,int y1,int x2,int y2,int k)

{

    if(corss(x1,y1,x2,y2,k) == false || tree[k].max == 0)  //矩形不相交或 矩形内max==0 则直接返回0

        return 0;

 

    if(x1<=tree[k].x1 && y1<=tree[k].y1 && tree[k].x2 <= x2 && tree[k].y2 <= y2) //如果要查询的矩形覆盖了当前矩形..则返回当前矩形的max

        return tree[k].max;

 

    int midx = (tree[k].x1+tree[k].x2)/2;

    int midy = (tree[k].y1+tree[k].y2)/2;

 

    float m[4] = {0,0,0,0};

 

    for(int i=0; i<4; i++)

        m[i] = Query(x1,y1,x2,y2,tree[k].ch[i]);

 

    float mm = m[0];

 

    for(int i=1; i<4; i++)

        mm = max(mm,m[i]);

 

    return mm;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值