二维数据结构---线段树

以前以为二维线段树非常神奇,实际接触后发现和一维线段树好像差不多,有点类似一个大线段树(x坐标)维护每一列的信息,每一列又是一个小线段树(y坐标),这就是线段树套线段树了,然后在网上终于找到了一篇和我以前写的一维线段树代码风格相近的代码,因为那篇博客也没什么注释讲解的,不过凭借对一维线段树的理解直接看代码还是比较好理解的,自己修补了许多改成了自己最熟悉也比较易懂的代码风格。

PS:这方面网上写的好的教程我还真没找到,只能靠多看来自己脑补了。

  POJ 2155

  给定一个01矩阵初始化所有元素为0,两种操作,一种给x1, y1, x2, y2四个坐标即两个点确定一个矩形将里面的值全部取反,一种给两个坐标x, y即一个点输出该点的值。

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <queue>
  6 #include <math.h>
  7 #include <string>
  8 #include <algorithm>
  9 #include <time.h>
 10 
 11 #define SIGMA_SIZE 26
 12 #define lson rt<<1
 13 #define rson rt<<1|1
 14 #define lowbit(x) (x&-x)
 15 #define foe(i, a, b) for(int i=a; i<=b; i++)
 16 #define fo(i, a, b) for(int i = a; i < b; i++);
 17 #pragma warning ( disable : 4996 )
 18 
 19 using namespace std;
 20 typedef long long LL;
 21 inline LL LMax(LL a, LL b) { return a>b ? a : b; }
 22 inline LL LMin(LL a, LL b) { return a>b ? b : a; }
 23 inline LL lgcd(LL a, LL b) { return b == 0 ? a : lgcd(b, a%b); }
 24 inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; }  //a*b = gcd*lcm
 25 inline int Max(int a, int b) { return a>b ? a : b; }
 26 inline int Min(int a, int b) { return a>b ? b : a; }
 27 inline int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); }
 28 inline int lcm(int a, int b) { return a / gcd(a, b)*b; }  //a*b = gcd*lcm
 29 const LL INF = 0x3f3f3f3f3f3f3f3f;
 30 const LL mod = 1000000007;
 31 const double eps = 1e-8;
 32 const int inf = 0x3f3f3f3f;
 33 const int maxk = 1e6 + 5;
 34 const int maxn = 4005;
 35 
 36 
 37 int N, Q, ans;
 38 bool g[maxn][maxn];
 39 
 40 void init()
 41 {
 42     cin >> N >> Q;
 43     memset(g, false, sizeof(g));
 44 }
 45 
 46 void y_update(int xrt, int yrt, int lhs, int rhs, int L, int R)
 47 {
 48     if (lhs <= L && rhs >= R)
 49     {
 50         g[xrt][yrt] ^= 1;
 51         return;
 52     }
 53 
 54     int mid = (L + R) >> 1;
 55     if (lhs <= mid) y_update(xrt, yrt << 1, lhs, rhs, L, mid);
 56     if (rhs >  mid) y_update(xrt, yrt << 1 | 1, lhs, rhs, mid + 1, R);
 57 }
 58 
 59 void x_update(int xrt, int L, int R, int x1, int y1, int x2, int y2)
 60 {
 61     if (x1 <= L && x2 >= R)
 62     {
 63         y_update(xrt, 1, y1, y2, 1, N);
 64         return;
 65     }
 66 
 67     int mid = (L + R) >> 1;
 68     if (x1 <= mid) x_update(xrt << 1, L, mid, x1, y1, x2, y2);
 69     if (x2 >  mid) x_update(xrt << 1 | 1, mid + 1, R, x1, y1, x2, y2);
 70 }
 71 
 72 void y_query(int xrt, int yrt, int L, int R, int y1)
 73 {
 74     ans ^= g[xrt][yrt];
 75     if (L == R)
 76         return;
 77 
 78     int mid = (L + R) >> 1;
 79     if (y1 <= mid) y_query(xrt, yrt << 1, L, mid, y1);
 80     else y_query(xrt, yrt << 1 | 1, mid + 1, R, y1);
 81 }
 82 
 83 //注意查找的操作
 84 void x_query(int xrt, int L, int R, int x1, int y1)
 85 {
 86     y_query(xrt, 1, 1, N, y1);
 87     if (L == R)
 88         return;
 89 
 90     int mid = (L + R) >> 1;
 91     if (x1 <= mid) x_query(xrt << 1, L, mid, x1, y1);
 92     else x_query(xrt << 1 | 1, mid + 1, R, x1, y1);
 93 }
 94 
 95 int main()
 96 {
 97     int all; cin >> all;
 98     while (all--)
 99     {
100         init();
101 
102         char str[3];
103         int x1, y1, x2, y2;
104         foe(i, 1, Q)
105         {
106             scanf("%s", str);
107             if (str[0] == 'C')
108             {
109                 scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
110                 x_update(1, 1, N, x1, y1, x2, y2);
111             }
112             else
113             {
114                 scanf("%d %d", &x1, &y1);
115                 ans = 0;
116                 x_query(1, 1, N, x1, y1);
117                 printf("%d\n", ans);
118             }
119         }
120         printf("\n");
121     }
122 
123     return 0;
124 }
View Code

 

  HDU 1823 Luck and Love

同样是一道二位线段树模板题,要求插入和查询最大两种操作,有点坑的地方就是给的值是浮点数, 把身高作为x轴,因为身高范围是100~200,操作时可以全部减100变成0~100范围,把活力值作为y轴,0.0~100.0可以全部乘10变成0~1000的范围,然后就是正常二维线段树了

PS:swap处理浮点数会掉精度

PPS:给你两个点可没告诉坐标是按大小顺序给的(太坑了)

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <queue>
  6 #include <math.h>
  7 #include <string>
  8 #include <algorithm>
  9 #include <time.h>
 10 
 11 #define SIGMA_SIZE 26
 12 #define lson rt<<1
 13 #define rson rt<<1|1
 14 #define lowbit(x) (x&-x)
 15 #define foe(i, a, b) for(int i=a; i<=b; i++)
 16 #define fo(i, a, b) for(int i = a; i < b; i++);
 17 #pragma warning ( disable : 4996 )
 18 
 19 using namespace std;
 20 typedef long long LL;
 21 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 22 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 23 inline LL lgcd( LL a, LL b )   { return b==0?a:lgcd(b,a%b); }
 24 inline LL llcm( LL a, LL b )   { return a/lgcd(a,b)*b; }  //a*b = gcd*lcm
 25 inline int Max(int a,int b)    { return a>b?a:b; }
 26 inline int Min(int a,int b)       { return a>b?b:a; }
 27 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 28 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 29 const LL INF = 0x3f3f3f3f3f3f3f3f;
 30 const LL mod  = 1000000007;
 31 const double eps = 1e-8;
 32 const int inf  = 0x3f3f3f3f;
 33 const int maxk = 1e6+5;
 34 const int maxn = 4020;
 35 
 36 int Q;
 37 int yuan[500][maxn];
 38 
 39 void y_build(int xrt, int rt, int L, int R )
 40 {
 41     yuan[xrt][rt] = -1;
 42     if ( L == R ) return;
 43 
 44     int mid = (L+R)>>1;
 45     y_build(xrt, lson, L, mid);
 46     y_build(xrt, rson, mid+1, R);
 47 }
 48 
 49 void x_build(int rt, int L, int R)
 50 {
 51     y_build(rt, 1, 0, 1000);
 52     if ( L == R ) return;
 53 
 54     int mid = (L+R)>>1;
 55     x_build(lson, L, mid);
 56     x_build(rson, mid+1, R);
 57 }
 58 
 59 void y_update(int xrt, int rt, int L, int R, int C, int love)
 60 {
 61     yuan[xrt][rt] = Max(love, yuan[xrt][rt]);
 62     if ( L == R )
 63         return;
 64 
 65     int mid = (L+R)>>1;
 66     if ( C <= mid ) y_update(xrt, lson, L, mid, C, love);
 67     else y_update(xrt, rson, mid+1, R, C, love);
 68 
 69     yuan[xrt][rt] = Max(yuan[xrt][lson], yuan[xrt][rson]);
 70 }
 71 
 72 void x_update(int rt, int L, int R, int h1, int a1, int love)
 73 {
 74     y_update(rt, 1, 0, 1000, a1, love);
 75     if ( L == R ) return;
 76 
 77     int mid = (L+R)>>1;
 78     if ( h1 <= mid ) x_update(lson, L, mid, h1, a1, love);
 79     else x_update(rson, mid+1, R, h1, a1, love);
 80 }
 81 
 82 int y_query(int xrt, int rt, int L, int R, int lhs, int rhs)
 83 {
 84     if ( lhs <= L && rhs >= R )
 85         return yuan[xrt][rt];
 86 
 87     int mid = (L+R)>>1, mmax = -1;
 88     if ( lhs <= mid ) mmax = Max(mmax, y_query(xrt, lson, L, mid, lhs, rhs));
 89     if ( rhs >  mid ) mmax = Max(mmax, y_query(xrt, rson, mid+1, R, lhs, rhs));
 90 
 91     return mmax;
 92 }
 93 
 94 int x_query(int rt, int L, int R, int h1, int a1, int h2, int a2)
 95 {
 96     if ( h1 <= L && h2 >= R )
 97         return y_query(rt, 1, 0, 1000, a1, a2);
 98 
 99     int mid = (L+R)>>1, mmax = -1;
100     if ( h1 <= mid ) mmax = Max(mmax, x_query(lson, L, mid, h1, a1, h2, a2));
101     if ( h2 >  mid ) mmax = Max(mmax, x_query(rson, mid+1, R, h1, a1, h2, a2));
102 
103     return mmax;
104 }
105 
106 int main()
107 {
108     while (~scanf("%d", &Q))
109     {
110         if (!Q) break;
111 
112         x_build(1, 0, 100);
113         char str[3];
114         int h1, h2, a1, a2, love, ans;
115         double d1, d2, dans;
116         while (Q--)
117         {
118             scanf("%s", str);
119             if (str[0] == 'I')
120             {
121                 scanf("%d %lf %lf", &h1, &d1, &d2);
122                 a1 = (d1*10); love = (d2*10);
123 
124                 x_update(1, 0, 100, h1-100, a1, love);
125             }
126             else
127             {
128                 scanf("%d %d %lf %lf", &h1, &h2, &d1, &d2);
129                 a1 = (d1*10); a2 = (d2*10);
130                 if (h1 > h2) swap(h1, h2);
131                 if (a1 > a2) swap(a1, a2);
132 
133                 ans = -1; dans = -1.0;
134                 ans = x_query(1, 0, 100, h1-100, a1, h2-100, a2);
135                 if (ans < 0) 
136                     printf("-1\n");
137                 else
138                 {
139                     dans = (double)ans / 10;
140                     printf("%.1lf\n", dans);
141                 }
142             }
143         }
144     }
145 
146     return 0;
147 }
View Code

 

posted @ 2018-07-24 13:55  LBNOQYX  阅读(607)  评论(0编辑  收藏  举报