首页 > 代码库 > hdu1823 Luck and Love 二维RMQ(二维线段树)

hdu1823 Luck and Love 二维RMQ(二维线段树)

题意:给定你二维范围,找这个范围里面的最大值

解题思路:二维线段树有两种实现方式,一种是  树套树  ,另一种则是将二维平面分成4块的  完全四叉树

我的代码:

// File Name: 1823.cpp// Author: darkdream// Created Time: 2014年07月10日 星期四 09时38分05秒#include<vector>#include<list>#include<map>#include<set>#include<deque>#include<stack>#include<bitset>#include<algorithm>#include<functional>#include<numeric>#include<utility>#include<sstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cmath>#include<cstdlib>#include<cstring>#include<ctime>#include<climits>#include<queue>using namespace std;struct ynode{    int ly,ry;     int v;};int L(int x){    return x << 1 ;}int R(int x){    return x * 2  + 1;}struct xnode{    int lx, rx;    struct ynode tt[1014<<2];}tree[112<<2];void build2(int x,int y,int ly ,int ry){    //   printf("%d %d %d\n",y,ly,ry);    tree[x].tt[y].ly = ly;    tree[x].tt[y].ry = ry;    tree[x].tt[y].v = -1;    if(ly == ry)        return ;    int m = (ly + ry )/2;     build2(x,L(y),ly,m);    build2(x,R(y),m+1,ry);}void build(int x,int lx,int rx){    build2(x,1,1,1005);    tree[x].lx = lx;     tree[x].rx = rx;     if(lx == rx)        return ;     int m = (lx + rx)/2;     build(L(x),lx,m);    build(R(x),m+1,rx);}void update2(int x, int y ,int fy,int v){    //    printf("%d %d %d\n",x,y,tree[x].tt[y].v);    int ly = tree[x].tt[y].ly;    int ry = tree[x].tt[y].ry;    if(ly == ry && ly == fy )    {        tree[x].tt[y].v = max(tree[x].tt[y].v,v);        return ;    }    if(ly == ry)        return ;     int m = (ly + ry)/2;     if(fy <= m )        update2(x,L(y),fy,v);    else update2(x,R(y),fy,v);    tree[x].tt[y].v = max(tree[x].tt[L(y)].v,tree[x].tt[R(y)].v);    //    printf("%d %d %d\n",x,y,tree[x].tt[y].v);}void update(int x,int fx ,int fy ,int v){    update2(x,1,fy,v);    if(tree[x].lx == tree[x].rx )    {        return ;     }    int m = (tree[x].lx + tree[x].rx) /2;     if(fx <= m )        update(L(x),fx,fy,v);    else update(R(x),fx,fy,v);}int ans = -1 ; void find2(int x, int y ,int ly,int ry){    if(ly <= tree[x].tt[y].ly && ry >= tree[x].tt[y].ry)    {//        printf("%d\n",tree[x].tt[y].v);        ans = max(ans,tree[x].tt[y].v);        return ;    }    int m = (tree[x].tt[y].ly + tree[x].tt[y].ry)/2;    if(ly <= m)        find2(x,L(y),ly,ry);    if(ry > m)        find2(x,R(y),ly,ry);}void find(int x,int lx,int rx ,int ly ,int ry){    if(lx <= tree[x].lx && rx >= tree[x].rx)    {        find2(x,1,ly,ry);        return;     }    int m = (tree[x].lx + tree[x].rx)/2;    if(lx <= m)        find(L(x),lx,rx,ly,ry);    if(rx > m )        find(R(x),lx,rx,ly,ry);}int main(){    int m ,tx,ty;    double ta,tb;    while(scanf("%d",&m) != EOF,m){        build(1,1,105);        char str[10];        for(int i = 1;i <= m; i++)        {            scanf("%s",str);            if(str[0] == I)            {                scanf("%d %lf %lf",&tx,&ta,&tb);                tx = tx - 99 ;                update(1,tx,int((ta + 1e-8)*10+1),int((tb + 1e-8)*10+1));            }else {                ans = -1;                double fx,fy;                scanf("%lf %lf %lf %lf",&fx,&fy,&ta,&tb);                tx = (((fx + 1e-8)*10)+9)/10.0 - 99;                ty = (fy +1e-8) - 99;                if(tx > ty)                {                  int temp =tx;                  tx = ty;                   ty = temp;                }                if(ta > tb)                {                  double temp =ta;                  ta = tb;                   tb = temp;                }                find(1,tx,ty,int((ta+1e-8)*10+1),int((tb+1e-8)*10+1));                if(ans == -1)                    printf("-1\n");                else printf("%.1lf\n",(ans-1)/10.0+1e-8);            }        }    }    return 0;}
View Code

 

胡浩的树套树代码:  http://www.notonlysuccess.com/index.php/segment-tree/

  1 struct Sub_Seg_Tree {  2     int left;  3     int right;  4     int val;  5     int mid() {  6         return (left + right) >> 1;  7     }  8 };  9 struct Seg_Tree{ 10     int left; 11     int right; 12     Sub_Seg_Tree tt[1001*4]; 13     int mid() { 14         return (left + right) >> 1; 15     } 16 }tt[101*4]; 17   18 void build2(Sub_Seg_Tree tt[],int l,int r,int idx) { 19     tt[idx].left = l; 20     tt[idx].right = r; 21     tt[idx].val = -1; 22     if(l == r)    return ; 23     int mid = tt[idx].mid(); 24     build2(tt,l,mid,LL(idx)); 25     build2(tt,mid+1,r,RR(idx)); 26 } 27   28 void build(int l,int r,int idx) { 29     build2(tt[idx].tt,0,1000,1); 30     tt[idx].left = l; 31     tt[idx].right = r; 32     if(l == r) return ; 33     int mid = tt[idx].mid(); 34     build(l,mid,LL(idx)); 35     build(mid+1,r,RR(idx)); 36 } 37   38 void update2(Sub_Seg_Tree tt[],int b,int val,int idx) { 39     if(tt[idx].left == tt[idx].right) { 40         checkmax(tt[idx].val,val); 41         return ; 42     } 43     if(b <= tt[idx].mid()) { 44         update2(tt,b,val,LL(idx)); 45     } else { 46         update2(tt,b,val,RR(idx)); 47     } 48     tt[idx].val = max(tt[LL(idx)].val,tt[RR(idx)].val); 49 } 50   51 void update(int a,int b,int val,int idx) { 52     update2(tt[idx].tt,b,val,1); 53     if(tt[idx].left == tt[idx].right) return ; 54     if(a <= tt[idx].mid()) { 55         update(a,b,val,LL(idx)); 56     } else { 57         update(a,b,val,RR(idx)); 58     } 59 } 60   61 int query2(Sub_Seg_Tree tt[],int l,int r,int idx) { 62     if(l <= tt[idx].left && r >= tt[idx].right) { 63         return tt[idx].val; 64     } 65     int mid = tt[idx].mid(); 66     int ret = -1; 67     if(l <= mid) checkmax(ret,query2(tt,l,r,LL(idx))); 68     if(mid < r) checkmax(ret,query2(tt,l,r,RR(idx))); 69     return ret; 70 } 71   72 int query(int l,int r,int l2,int r2,int idx) { 73     if(l <= tt[idx].left && r >= tt[idx].right) { 74         return query2(tt[idx].tt,l2,r2,1); 75     } 76     int mid = tt[idx].mid(); 77     int ret = -1; 78     if(l <= mid) checkmax(ret,query(l,r,l2,r2,LL(idx))); 79     if(mid < r) checkmax(ret,query(l,r,l2,r2,RR(idx))); 80     return ret; 81 } 82   83 int main() { 84     int T; 85     while(scanf("%d",&T) == 1) { 86         if(T == 0)    break; 87         build(100,200,1); 88         while(T --) { 89             char op; 90             while(!isalpha(op = getchar())); 91             if(op == I) { 92                 int a; 93                 double b,c; 94                 scanf("%d%lf%lf",&a,&b,&c); 95                 update(a,int(b*10),int(c*10),1); 96             } else { 97                 int l1,r1; 98                 double l2,r2; 99                 scanf("%d%d%lf%lf",&l1,&r1,&l2,&r2);100                 if(l1 > r1) swap(l1,r1);101                 if(l2 > r2) swap(l2,r2);102                 int ret = query(l1,r1,int(l2*10),int(r2*10),1);103                 if(ret < 0) {104                     puts("-1");105                 } else {106                     printf("%.1lf\n",ret/10.0);107                 }108             }109         }110     }111     return 0;112 }
View Code

 

英雄哪里出来的  完全四叉树代码:  http://www.cppblog.com/menjitianya/archive/2011/03/30/143010.aspx

  1 /*  2 题意:  3     给定一个n*n(n <= 300)的矩阵,然后是(T <= 10^6)次询问,每次询问某个子矩  4 阵中的最小值。  5   6 解法:  7 二维线段树 或者 二维RMQ  8   9 思路: 10     一维线段树是一颗完全二叉树,那么二维线段树无疑就是一颗完全四叉树,换言 11 之,每个结点有四个儿子,这里为了空间不浪费,将所有结点记录在一个一维数组中 12 ,每个结点的四个儿子采用编号的方式存储,在建树之前将每个结点的信息全部初始 13 化,初始化的时候需要注意的是每次将当前结点的四个儿子清空,然后判断它本身是 14 否是叶子结点,可以通过x和y区间端点是否重合来判断,最后再来生成四个儿子编号 15 ,然后往下递归,递归结束后根据四个儿子的最小值更新当前的最小值。再来看询问 16 ,和一维的情况类似,一维是对区间交,而二维则是对矩形交,如果询问的二维区间 17 和当前结点管理的二维区间没有交集,显然不可能有最小值,直接返回inf,否则如果 18 询问的二维区间完全包含了当前结点管理的二维区间,那么返回结点最小值。否则递 19 归当前结点的四个儿子,取最小值,回归到根节点就得到了询问区间的最值了。 20     需要注意的是在建树的时候不要在叶子结点生成多余的儿子结点,这样内存会多 21 一倍,如果开得不够大有可能下标越界,开得太大有可能超内存。还有就是在二维线 22 段树的结点上信息会多了不少,能节省空间尽量节省,比如每个结点管理的区间端点 23 不可能很大,所以不需要int,short就足够了。 24 */ 25  26 #include <iostream> 27 #include <cstring> 28 #include <cstdio> 29  30 using namespace std; 31  32 #define maxn 310 33 #define inf  (1<<30)-1 34  35 struct Tree { 36     int Min;           // 当前结点区间最小值 37     int son[4];        // 四个儿子在数组中的编号 38     short x[2], y[2];  // 当前结点管理的二维区间 39 }T[maxn*maxn*5]; 40  41 int Tree_Id; 42  43 int n; 44 int mat[maxn][maxn]; 45  46 void Build(int fat, int x0, int x1, int y0, int y1) { 47     int i; 48     for(i = 0; i < 4; i++) { 49         T[fat].son[i] = 0; 50     } 51     T[fat].x[0] = x0;  T[fat].x[1] = x1; 52     T[fat].y[0] = y0;  T[fat].y[1] = y1; 53  54     if(x0 == x1 && y0 == y1) { 55         T[fat].Min = mat[x0][y0]; 56         return ; 57     } 58     for(i = 0; i < 4; i++) { 59         T[fat].son[i] = Tree_Id++; 60     } 61  62     int xmid = (x0 + x1) >> 1; 63     int ymid = (y0 + y1) >> 1; 64     Build(T[fat].son[0], x0, xmid,   y0, ymid); 65     Build(T[fat].son[1], x0, xmid,   (ymid<y1) ? ymid+1 : ymid, y1); 66     Build(T[fat].son[2], (xmid<x1) ? xmid+1 : xmid, x1, y0, ymid); 67     Build(T[fat].son[3], (xmid<x1) ? xmid+1 : xmid, x1, (ymid<y1) ? ymid+1 : ymid, y1); 68  69     T[fat].Min = T[T[fat].son[0]].Min; 70     for(i = 1; i < 4; i++) { 71         if(T[T[fat].son[i]].Min < T[fat].Min) 72             T[fat].Min = T[T[fat].son[i]].Min; 73     } 74 } 75  76 int Query(int fat, int x0, int x1, int y0, int y1) { 77     if(x0 > T[fat].x[1] || x1 < T[fat].x[0] 78     || y0 > T[fat].y[1] || y1 < T[fat].y[0]) { 79         return inf; 80     } 81  82     if(x0 <= T[fat].x[0] && T[fat].x[1] <= x1 83         && y0 <= T[fat].y[0] && T[fat].y[1] <= y1) { 84         return T[fat].Min; 85     } 86     int i; 87     int Min = inf; 88     for(i = 0; i < 4; i++) { 89         int v = Query(T[fat].son[i], x0, x1, y0, y1); 90         if(v < Min) 91             Min = v; 92     } 93     return Min; 94 } 95  96 int main() { 97     int t; 98     int i, j; 99 100     scanf("%d", &t);101     while(t--) {102         scanf("%d", &n);103         Tree_Id = 0;104         for(i = 1; i <= n; i++) {105             for(j = 1; j <= n; j++) {106                 scanf("%d", &mat[i][j]);107             }108         }109         Tree_Id = 2;110         Build(1, 1, n, 1, n);111 112         int m;113         scanf("%d", &m);114 115         while(m--) {116             int r[2], c[2];117             scanf("%d %d %d %d", &r[0], &c[0], &r[1], &c[1]);118             printf("%d\n", Query(1, r[0], r[1], c[0], c[1]));119         }120     }121     return 0;122 }
View Code