zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",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
    ");
                    else printf("%.1lf
    ",(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
    ",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
    ", Query(1, r[0], r[1], c[0], c[1]));
    119         }
    120     }
    121     return 0;
    122 }
    View Code
    没有梦想,何谈远方
  • 相关阅读:
    hdu 2553 N皇后问题(dfs)
    hdu 1043 Eight(双向bfs)
    牛人的ACM经验 (转)
    康托和逆康托展开(转)
    hiho Mission Impossible 6(模拟 未提交验证。。)
    数组越界也可以这么巧~~~
    poj 1679 The Unique MST(次小生成树)
    zoj 3204 Connect them(最小生成树)
    hdu 4463 Outlets(最小生成树)
    廖雪峰Java1-2程序基础-8字符和字符串
  • 原文地址:https://www.cnblogs.com/zyue/p/3844932.html
Copyright © 2011-2022 走看看