赞
踩
1.更改单点,输出区间和
一般用向上修改,向下统计, 也就是在updata函数里面使用+=,在 sum函数里面使用-=
完整代码如下
- void updata(int x, int num)
- {
- while (x <= n) //树状数组的大小
- {
- bit[x] += num;
- x += lowbit(x); //lowbit返回2^k 函数内容为return x&-x;
- }
- }
- int sum(int x)
- {
- int sum = 0;
- while (x > 0)
- {
- sum += bit[x];
- x -= lowbit(x);
- }
- return sum;
- }
例题如下 杭电 敌兵布阵
题意就是对n个阵地中的某个,进行数目的加减操作,然后输出从a到b阵地的总人数。
代码如下:
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <map>
- #include <string>
- #include <cstdlib>
-
- using namespace std;
- const int MAXN = 50000 + 10;
- int BIT[MAXN], t;
-
- int lowbit(int x)
- {
- return x&-x;
- }
-
- void updata(int x, int num)
- {
- while (x <= t)
- {
- BIT[x] += num;
- x += lowbit(x);
- }
- }
-
- int sum(int x)
- {
- int sum = 0;
- while (x > 0)
- {
- sum += BIT[x];
- x -= lowbit(x);
- }
- return sum;
- }
-
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- #endif // LOCAL
- int T;
- int num, a, b;
- int Ncase = 1;
- scanf("%d", &T);
- while (T--)
- {
- memset(BIT, 0, sizeof(BIT));
- scanf("%d", &t);
- for (int i = 1; i <= t; ++i)
- {
- scanf("%d", &num);
- updata(i, num); //单点更新
- }
- printf("Case %d:\n", Ncase++);
- char command[10];
- while (scanf("%s", command) != EOF)
- {
- if (command[0] == 'E')
- break;
- scanf("%d%d", &a, &b);
- if (command[0] == 'S')
- updata(a, -b); //单点更新
- else if (command[0] == 'A')
- updata(a, b); //单点更新
- else
- printf("%d\n", sum(b) - sum(a-1)); //返回总和 因为sum(b) 返回从1到b的值,然后 sum(a-1)返回从1到a-1的值 相减就是a到b的值。
- }
- }
- return 0;
- }
2.更改区间,输出单点
一般用向下修改,向上统计, 也就是在updata函数里面使用-=,在 sum函数里面使用+=
完整代码如下
- void updata(int x, int num)
- {
- while (x > 0)
- {
- bit[x] += num;
- x -= lowbit(x); //lowbit返回2^k 函数内容为return x&-x;
- }
- }
- int sum(int x)
- {
- int sum = 0;
- while (x <= n) //树状数组的大小
- {
- sum += bit[x];
- x += lowbit(x);
- }
- return sum;
- }
例题如下杭电 Color the ball
题意 在一段连续的区间上 从a到b依次 涂色 也就是值+1 然后输出某个单点的值
代码如下
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <map>
- #include <string>
- #include <cstdlib>
-
- using namespace std;
- const int MAXN = 100000 + 10;
- int bit[MAXN], n;
-
- int lowbit(int x)
- {
- return x&-x;
- }
-
- void updata(int x, int num)
- {
- while (x > 0)
- {
- bit[x] += num;
- x -= lowbit(x);
- }
- }
-
- int sum(int x)
- {
- int sum = 0;
- while (x <= n)
- {
- sum += bit[x];
- x += lowbit(x);
- }
- return sum;
- }
-
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- #endif // LOCAL
- int a, b;
- while (scanf("%d", &n) != EOF && n != 0)
- {
- memset(bit, 0 ,sizeof(bit));
- for (int i = 1; i <= n; ++i)
- {
- scanf("%d%d", &a, &b);
- updata(b, 1); //单点更新
- updata(a - 1, -1); //单点更新
- }
- printf("%d", sum(1)); //因为单点更新的时候取+1, -1 相互抵消,所以sum(1)就是单点的值
- for (int i = 2; i <= n; ++i)
- printf(" %d", sum(i));
- printf("\n");
- }
- return 0;
- }
一维树状数组更新和求和可以在数轴上进行模拟,用区间来表示。理解更快。
二维树状数组在操作是,是以二维的直角坐标系为基准,在更新时应该注意边界问题
1.单点更新,输出区间
在updata里面使用 += 在Query里面使用-=
实例如下
- void updata(int x, int y, int num)
- {
- int temp = x;
- while (y <= n)
- {
- x = temp;
- while (x <= n)
- {
- bit[x][y] += num;
- x += lowbit(x);
- }
- y += lowbit(y);
- }
- }
- int Query(int x, int y)
- {
- int sum = 0;
- int temp = x;
- while (y > 0)
- {
- x = temp; //指针一定要初始化
- while (x > 0)
- {
- sum += bit[x][y];
- x -= lowbit(x);
- }
- y -= lowbit(y);
- }
- return sum;
- }
例题
POJ Mobile phones
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <map>
- #include <string>
- #include <list>
- #include <vector>
- #include <cstdlib>
-
- using namespace std;
- const int MAXN = 1250;
- int bit[MAXN][MAXN], n;
- int lowbit(int x)
- {
- return x&-x;
- }
-
- void updata(int x, int y, int num)
- {
- int temp = x;
- while (y <= n)
- {
- x = temp;
- while (x <= n)
- {
- bit[x][y] += num;
- x += lowbit(x);
- }
- y += lowbit(y);
- }
- }
-
- int Query(int x, int y)
- {
- int sum = 0;
- int temp = x;
- while (y > 0)
- {
- x = temp;
- while (x > 0)
- {
- sum += bit[x][y];
- x -= lowbit(x);
- }
- y -= lowbit(y);
- }
- return sum;
- }
-
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- #endif // LOCAL
- int com;
- int x, y, a, b;
- while (scanf("%d", &com) != EOF && com != 3)
- {
-
- if (com == 0)
- {
- scanf("%d", &n);
- memset(bit, 0, sizeof(bit));
- }
- else if (com == 1)
- {
- scanf("%d%d%d", &x, &y, &a);
- updata(x + 1, y + 1, a); //单点向上更新
- }
- else
- {
- scanf("%d%d%d%d", &x, &y, &a, &b);
- x++; y++; a++; b++;
-
- printf("%d\n", Query(a, b) - Query(a, y - 1) - Query(x - 1, b) + Query(x - 1, y - 1)); //向下求和 求和注意筛选区间以及边界问题
- }
- }
- return 0;
- }
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <map>
- #include <string>
- #include <cstdlib>
-
- using namespace std;
- const int MAXN = 1010;
- int bit[MAXN][MAXN], n;
-
- int lowbit(int x)
- {
- return x&-x;
- }
-
- void updata(int x, int y, int num)
- {
- int temp = x;
- while (y <= n)
- {
- x = temp;
- while (x <= n)
- {
- bit[x][y] += num;
- x += lowbit(x);
- }
- y += lowbit(y);
- }
- }
-
- int Query(int x, int y)
- {
- int sum = 0;
- int temp = x;
- while ( y > 0)
- {
- x = temp;
- while( x > 0)
- {
- sum += bit[x][y];
- x -= lowbit(x);
- }
- y -= lowbit(y);
- }
- return sum;
- }
-
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt", "r", stdin);
- //freopen("out.txt", "w", stdout);
- #endif // LOCAL
- int t, T;
- int blank = 0;
- int x1, x2, y1, y2;
- scanf("%d", &T);
- while (T--)
- {
- memset(bit, 0, sizeof(bit));
- scanf("%d%d", &n, &t);
- if (blank++ != 0)
- printf("\n");
- while (t--)
- {
- char command[3];
- scanf("%s", command);
- if (command[0] == 'C')
- {
- scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
- updata(x1, y1, 1);
- updata(x2 + 1, y1, -1);
- updata(x1, y2 + 1, -1);
- updata(x2 + 1, y2 + 1, 1); //更新时 区间的选用 参照上面的图片
- }
- else
- {
- scanf("%d%d", &x1, &y1);
- printf("%d\n", Query(x1, y1) % 2);
- }
- }
- }
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。