随笔 - 97, 文章 - 22, 评论 - 81, 引用 - 0
数据加载中……

HDU 1823 Luck and Love

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1823

/*
题意:
    二维区间求最大值。

解法:
二维线段树 或者 二维RMQ

思路:
    一维线段树是一颗完全二叉树,那么二维线段树无疑就是一颗完全四叉树,换言
之,每个结点有四个儿子,这里为了空间不浪费,将所有结点记录在一个一维数组中
,每个结点的四个儿子采用编号的方式存储,在建树之前将每个结点的信息全部初始
化,初始化的时候需要注意的是每次将当前结点的四个儿子清空,然后判断它本身是
否是叶子结点,可以通过x和y区间端点是否重合来判断,最后再来生成四个儿子编号
,然后往下递归,递归结束后根据四个儿子的最小值更新当前的最小值。再来看询问
,和一维的情况类似,一维是对区间交,而二维则是对矩形交,如果询问的二维区间
和当前结点管理的二维区间没有交集,显然不可能有最小值,直接返回inf,否则如果
询问的二维区间完全包含了当前结点管理的二维区间,那么返回结点最小值。否则递
归当前结点的四个儿子,取最小值,回归到根节点就得到了询问区间的最值了。
    需要注意的是在建树的时候不要在叶子结点生成多余的儿子结点,这样内存会多
一倍,如果开得不够大有可能下标越界,开得太大有可能超内存。还有就是在二维线
段树的结点上信息会多了不少,能节省空间尽量节省,比如每个结点管理的区间端点
不可能很大,所以不需要int,short就足够了。

*/

#include 
<iostream>
#include 
<cmath>
#include 
<algorithm>
using namespace std;

#define maxn 200010
#define eps 1e-6
typedef 
double Type;


Type bin[maxn];
int size, tot;

int B(Type val) {
    
int l = 0;
    
int r = tot-1;
    
while(l <= r) {
        
int m = (l + r) >> 1;
        
if(fabs(bin[m] - val) < eps)
            
return m;
        
if(val > bin[m]) {
            l 
= m + 1;
        }
else
            r 
= m - 1;
    }

}



struct Op {
    
int mode;
    Type HH, AA, L;
    Type H[
2], A[2];

    
void SCANF(int _mode) {
        mode 
= _mode;
        
if(mode == 0{
            
// 插入操作
            scanf("%lf %lf %lf"&HH, &AA, &L);
            bin[size
++= HH;
            bin[size
++= AA;
        }
else {
            
// 询问操作
            scanf("%lf %lf %lf %lf"&H[0], &H[1], &A[0], &A[1]);
            
for(int i = 0; i < 2; i++{
                bin[size
++= H[i];
                bin[size
++= A[i];
            }

            
if(H[0> H[1]) swap(H[0], H[1]);
            
if(A[0> A[1]) swap(A[0], A[1]);
        }

    }

}
O[maxn];


struct Tree {
    
int son[4];
    Type Max;

    
void clear() {
        Max 
= -1;
        
for(int i = 0; i < 4; i++)
            son[i] 
= -1;
    }

}
T[maxn*4];
int all;

Type MMax(Type a, Type b) 
{
    
return a > b ? a : b;
}


void Insert(int& root, int x, int y, int lx, int rx, int ly, int ry, Type Max) {
    
if(x > rx || x < lx || y > ry || y < ly)
        
return ;
    
if(root == -1{
        root 
= all++;
        T[root].clear();
    }

    T[root].Max 
= MMax(T[root].Max, Max);

    
if(lx == rx && ly == ry)
        
return ;

    
int midx0 = (lx + rx) >> 1;
    
int midy0 = (ly + ry) >> 1;
    
int midx1 = (lx==rx) ? midx0 : midx0 + 1;
    
int midy1 = (ly==ry) ? midy0 : midy0 + 1;

    Insert(T[root].son[
0], x, y, lx, midx0, ly, midy0, Max);
    Insert(T[root].son[
1], x, y, lx, midx0, midy1, ry, Max);
    Insert(T[root].son[
2], x, y, midx1, rx, ly, midy0, Max);
    Insert(T[root].son[
3], x, y, midx1, rx, midy1, ry, Max);
}


void Query(int root, int x0, int x1, int y0, int y1, 
                      
int lx, int rx, int ly, int ry, Type& Max) {
    
if(x0 > rx || x1 < lx || y0 > ry || y1 < ly || root == -1 || T[root].Max <= Max)
        
return ;
    
if(x0 <= lx && rx <= x1 && y0 <= ly && ry <= y1) {
        Max 
= MMax(Max, T[root].Max);
        
return ;
    }


    
int midx0 = (lx + rx) >> 1;
    
int midy0 = (ly + ry) >> 1;
    
int midx1 = (lx==rx) ? midx0 : midx0 + 1;
    
int midy1 = (ly==ry) ? midy0 : midy0 + 1;
    
    Query(T[root].son[
0], x0, x1, y0, y1, lx, midx0, ly, midy0, Max);
    Query(T[root].son[
1], x0, x1, y0, y1, lx, midx0, midy1, ry, Max);
    Query(T[root].son[
2], x0, x1, y0, y1, midx1, rx, ly, midy0, Max);
    Query(T[root].son[
3], x0, x1, y0, y1, midx1, rx, midy1, ry, Max);
}


int n;
int main() {
    
int i;
    
char str[10];

    
while(scanf("%d"&n) != EOF && n) {
        size 
= 0;
        all 
= 0;
        
for(i = 0; i < n; i++{
            scanf(
"%s", str);
            
if(!strcmp(str, "I")) {
                O[i].SCANF(
0);
            }
else {
                O[i].SCANF(
1);
            }

        }

        sort(bin, bin 
+ size);
        tot 
= 0;
        
for(i = 0; i < size; i++{
            
if(!|| fabs(bin[i] - bin[i-1]) > eps) {
                bin[tot
++= bin[i];
            }

        }


        
int root = -1;

        
for(i = 0; i < n; i++{
            
if(O[i].mode == 0{
                Insert(root, B(O[i].HH), B(O[i].AA), 
0, tot - 10, tot - 1, O[i].L);
            }
else {
                Type ans 
= -1;
                Query(root, B(O[i].H[
0]), B(O[i].H[1]), B(O[i].A[0]), B(O[i].A[1]), 0, tot - 10, tot - 1, ans);
                
if(ans < 0{
                    printf(
"-1\n");
                }
else
                    printf(
"%.1lf\n", ans);
            }

        }

    }

    
return 0;
}

posted on 2011-04-03 22:17 英雄哪里出来 阅读(1846) 评论(0)  编辑 收藏 引用 所属分类: 线段树


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理