以前以为二维线段树非常神奇,实际接触后发现和一维线段树好像差不多,有点类似一个大线段树(x坐标)维护每一列的信息,每一列又是一个小线段树(y坐标),这就是线段树套线段树了,然后在网上终于找到了一篇和我以前写的一维线段树代码风格相近的代码,因为那篇博客也没什么注释讲解的,不过凭借对一维线段树的理解直接看代码还是比较好理解的,自己修补了许多改成了自己最熟悉也比较易懂的代码风格。
PS:这方面网上写的好的教程我还真没找到,只能靠多看来自己脑补了。
POJ 2155
给定一个01矩阵初始化所有元素为0,两种操作,一种给x1, y1, x2, y2四个坐标即两个点确定一个矩形将里面的值全部取反,一种给两个坐标x, y即一个点输出该点的值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ", ans); 118 } 119 } 120 printf(" "); 121 } 122 123 return 0; 124 }
HDU 1823 Luck and Love
同样是一道二位线段树模板题,要求插入和查询最大两种操作,有点坑的地方就是给的值是浮点数, 把身高作为x轴,因为身高范围是100~200,操作时可以全部减100变成0~100范围,把活力值作为y轴,0.0~100.0可以全部乘10变成0~1000的范围,然后就是正常二维线段树了
PS:swap处理浮点数会掉精度
PPS:给你两个点可没告诉坐标是按大小顺序给的(太坑了)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 "); 137 else 138 { 139 dans = (double)ans / 10; 140 printf("%.1lf ", dans); 141 } 142 } 143 } 144 } 145 146 return 0; 147 }