二维线段树之树套树

Posted daybreaking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二维线段树之树套树相关的知识,希望对你有一定的参考价值。

  1 //poj1195 二维线段树之树套树
  2 // 先确定横坐标所在的区间并记录该结点的编号p,然后再确定纵坐标所在的区间并记录该结点的编号cur,则tree[cur][p]为目标区间。
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <queue>
  9 #include <stack>
 10 #include <deque>
 11 #include <map>
 12 #include <iostream>
 13 using namespace std;
 14 typedef long long LL;
 15 const double pi = acos(-1.0);
 16 const double e = exp(1);
 17 //const int MAXN =2e5+10;
 18 const int N = 1055;
 19 
 20 //const int maxn = 1024 * 1024 * 1.5;
 21 
 22 int n;
 23 int sum[N * 3][N * 3];
 24 
 25 void updatey(int y, int l, int r, int cur, int p, int op, int val)
 26 // 纵坐标目标值,待找区间的左端点,待找区间的右端点,y中树的结点的下标,已找到的横坐标中结点的下标,值更新的方式,需要更新的值
 27 {
 28     if(l == r)
 29     {
 30         if(op == 1)  //根据题目要求,对目标值直接修改
 31         {
 32             sum[p][cur] += val;
 33         }
 34         else   // 回溯过程中,维护树的结构
 35         {
 36             sum[p][cur] = sum[p << 1][cur] + sum[p << 1 | 1][cur];
 37         }
 38         return ;
 39     }
 40     int mid = (l + r) >> 1;
 41     if(y <= mid)   //当前结点的左孩子区间需要找
 42     {
 43         updatey(y, l, mid, cur << 1, p, op, val);
 44     }
 45     else  // 当前结点的右孩子区间需要找
 46     {
 47         updatey(y, mid + 1, r, cur << 1 | 1, p, op, val);
 48     }
 49     sum[p][cur] = sum[p][cur << 1] + sum[p][cur << 1 | 1];
 50 
 51 }
 52 
 53 void updatex(int x, int y, int l, int r, int cur, int val)
 54 {
 55     if(l == r)
 56     {
 57         updatey(y, 1, n, 1, cur, 1, val);   //锁定了横坐标所在的结点cur,再去寻找纵坐标所在的结点。
 58         return ; 
 59     }
 60     int mid = (l + r) >> 1;
 61     if(x <= mid)
 62     {
 63         updatex(x, y, l, mid, cur << 1, val);
 64     }
 65     else
 66     {
 67         updatex(x, y, mid + 1, r, cur << 1 | 1, val);
 68     }
 69     updatey(y, 1, n, 1, cur, 2, val);
 70 }
 71 
 72 int queryy(int ly, int ry, int l, int r, int cur, int p)
 73 {
 74     if(ly <= l && ry >= r)
 75     {
 76         return sum[p][cur];
 77     }
 78     int res = 0;
 79     int mid = (l + r) >> 1;
 80     if(ly <= mid)
 81     {
 82         res += queryy(ly, ry, l, mid, cur << 1, p);
 83     }
 84     if(ry > mid)
 85     {
 86         res += queryy(ly, ry, mid + 1, r, cur << 1 | 1, p);
 87     }
 88     return res;
 89 }
 90 
 91 int queryx(int lx, int rx, int ly, int ry, int l, int r, int cur)
 92 {
 93     int res = 0;
 94     if(lx <= l && rx >= r)
 95     {
 96         res = queryy(ly, ry, 1, n, 1, cur);
 97         return res;
 98     }
 99     int mid = (l + r) >> 1;
100     if(lx <= mid)
101     {
102         res += queryx(lx, rx, ly, ry, l, mid, cur << 1);
103     }
104     if(rx > mid)
105     {
106         res += queryx(lx, rx, ly, ry, mid + 1, r, cur << 1 | 1);
107     }
108     return res;
109 }
110 
111 
112 int main()
113 {
114     int i, j, t;
115     int x1, y1, x2, y2, c;
116 
117     while(scanf("%d",&t) != EOF)
118     {
119         if(t == 3)
120             break;
121         if(t == 0)
122         {
123             scanf("%d",&n);
124             n ++;
125             memset(sum, 0, sizeof(sum));
126         }
127         else if(t == 1)
128         {
129             scanf("%d%d%d", &x1, &y1, &c);
130             x1 ++, y1 ++;
131             updatex(x1, y1, 1, n, 1, c);
132         }
133         else if(t == 2)
134         {
135             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
136             x1++, y1++, x2++, y2++;
137             printf("%d
", queryx(x1, x2, y1, y2, 1, n, 1));
138         }
139     }
140 
141     return 0;
142 }

 

以上是关于二维线段树之树套树的主要内容,如果未能解决你的问题,请参考以下文章

树套树+UVALive6709 Mosaic 二维线段树

#树套树,二维线段树#HDU 4819 Mosaic

[POJ2155] Matrix(二维线段树,树套树)

BZOJ4785[Zjoi2017]树状数组 树套树(二维线段树)

树套树乱讲

浅谈二维线段树的几种不同的写法