题目大意

给定一个S*S的矩形,该矩形由S*S个1x1的单元格构成,每个单元格内可以放一个整数,每次有如下可能操作: 
(1)改变某个单位单元格中的数的大小 
(2)查询由若干个连续单元格构成的X*Y的大小的矩形内所有数的总和

题目分析

典型的区间操作,而且是单点更新,区间查询。因此使用树状数组,不过应该使用二维树状数组。二维树状数组和一维其实没什么区别。。。。 
    另:用线段树也做了一份,但是超时,果然树状数组在效率上还是略胜线段树的。下面给出树状数组的AC代码和线段树的TLE代码。

实现(c++)

1.树状数组

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#define MAX_SQUARE_SIZE 1025
#define MAX(a, b) a>b? a:b
#define MIN(a, b) a <b? a:b
int gLowBit[MAX_SQUARE_SIZE];
int gC[MAX_SQUARE_SIZE][MAX_SQUARE_SIZE]; void InitLowBit(int n){
for (int i = 1; i <= n; i++){
gLowBit[i] = i&(-i);
}
} void InitSequence(int n){
memset(gC, 0, sizeof(gC));
} void Update(int x, int y, int n, int add){
int tmp_y = y;
while (x <= n){
y = tmp_y;
while (y <= n){
gC[x][y] += add;
y += gLowBit[y];
}
x += gLowBit[x];
}
}
int Query1(int x, int y){
int tmp_y = y, result = 0;
while (x > 0){
y = tmp_y;
while (y > 0){
result += gC[x][y];
y -= gLowBit[y];
}
x -= gLowBit[x];
}
return result;
} int Query(int left, int right, int bottom, int top){
int r_t = Query1(right, top);
int l_t = Query1(left - 1, top);
int r_b = Query1(right, bottom - 1);
int l_b = Query1(left - 1, bottom - 1); //注意在查询的时候,需要计算的矩形的边界弄清楚 [i , ... j] = sum(j) = sum(i - 1)
return (r_t + l_b - l_t - r_b);
}
int main(){
int ins;
int S, X, Y, A, L, B, R, T;
scanf("%d %d", &ins, &S);
InitLowBit(S);
InitSequence(S);
while (scanf("%d", &ins)){
if (ins == 3){
break;
}
if (ins == 1){
scanf("%d %d %d", &X, &Y, &A);
Update(X+1, Y+1, S, A);
}
else if (ins == 2){
scanf("%d %d %d %d", &L, &B, &R, &T);
int result = Query(L+1, R+1, B+1, T+1);
printf("%d\n", result);
}
}
return 0;
}

2.线段树

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define MAX_SQUARE_SIZE 1025
#define MAX_NODE_NUM MAX_SQUARE_SIZE*4
#define MAX(a, b) a>b? a:b
#define MIN(a, b) a <b? a:b
struct Node{
short left;
short right;
short top;
short bottom;
int sum_phones;
short h_mid(){
return (left + right) >> 1;
}
short v_mid(){
return (top + bottom) >> 1;
}
};
Node gNodes[MAX_NODE_NUM][MAX_NODE_NUM];
void BuildTree(int h_index, int v_index, short left, short right, short bottom, short top){
gNodes[h_index][v_index].left = left;
gNodes[h_index][v_index].right = right;
gNodes[h_index][v_index].top = top;
gNodes[h_index][v_index].bottom = bottom;
gNodes[h_index][v_index].sum_phones = 0;
if (left == right || top == bottom){
return;
}
int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
short h_mid = (left + right) >> 1, v_mid = (top + bottom) >> 1;
BuildTree(left_child, down_child, left, h_mid, bottom, v_mid);
BuildTree(right_child, down_child, h_mid + 1, right, bottom, v_mid);
BuildTree(left_child, up_child, left, h_mid, v_mid + 1, top);
BuildTree(right_child, up_child, h_mid + 1, right, v_mid + 1, top);
} void Update(int h_index, int v_index, short left, short right, short bottom, short top, int add){
if (gNodes[h_index][v_index].left == gNodes[h_index][v_index].right){ //arrive to the point
gNodes[h_index][v_index].sum_phones += add;
return;
}
if (left > gNodes[h_index][v_index].right || right < gNodes[h_index][v_index].left
|| top < gNodes[h_index][v_index].bottom || bottom > gNodes[h_index][v_index].top){
return;
}
if (left > right || bottom > top){
return;
}
int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
short h_mid = gNodes[h_index][v_index].h_mid(), v_mid = gNodes[h_index][v_index].v_mid();
gNodes[h_index][v_index].sum_phones += add;
Update(left_child, down_child, left, MIN(right, h_mid), bottom, MIN(top, v_mid), add);
Update(left_child, up_child, left, MIN(right, h_mid), MAX(v_mid + 1, bottom), top, add);
Update(right_child, down_child, MAX(left, h_mid + 1), right, bottom, MIN(top, v_mid), add);
Update(right_child, down_child, MAX(left, h_mid + 1), right, MAX(v_mid + 1, bottom), top, add);
} int Query(int h_index, int v_index, short left, short right, short bottom, short top){
if (left == right || top == bottom){ //arrive to the point
return gNodes[h_index][v_index].sum_phones;
}
if (left > gNodes[h_index][v_index].right || right < gNodes[h_index][v_index].left
|| top < gNodes[h_index][v_index].bottom || bottom > gNodes[h_index][v_index].top){
return 0;
}
if (left > right || bottom > top){
return 0;
}
int left_child = 2 * h_index + 1, right_child = 2 * h_index + 2;
int up_child = 2 * v_index + 1, down_child = 2 * v_index + 2;
short h_mid = gNodes[h_index][v_index].h_mid(), v_mid = gNodes[h_index][v_index].v_mid();
int result = 0;
result += Query(left_child, down_child, left, MIN(right, h_mid), bottom, MIN(top, v_mid));
result += Query(left_child, up_child, left, MIN(right, h_mid), MAX(v_mid + 1, bottom), top);
result += Query(right_child, down_child, MAX(left, h_mid + 1), right, bottom, MIN(top, v_mid));
result += Query(right_child, down_child, MAX(left, h_mid + 1), right, MAX(v_mid + 1, bottom), top);
return result;
} int main(){
int ins;
int S, X, Y, A, L, B, R, T;
scanf("%d %d", &ins, &S);
BuildTree(0, 0, 0, S - 1, 0, S - 1);
while (scanf("%d", &ins)){
if (ins == 3){
break;
}
if (ins == 1){
scanf("%d %d %d", &X, &Y, &A);
Update(0, 0, X, X, Y, Y, A);
}
else if (ins == 2){
scanf("%d %d %d %d", &L, &B, &R, &T);
int result = Query(0, 0, L, R, B, T);
printf("%d\n", result);
}
}
return 0;
}

poj_1190 树状数组的更多相关文章

  1. BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2221  Solved: 1179[Submit][Sta ...

  2. bzoj1878--离线+树状数组

    这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...

  3. codeforces 597C C. Subsequences(dp+树状数组)

    题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  5. BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status] ...

  6. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

  7. 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

    E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

  8. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

  9. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

随机推荐

  1. PHP的HashTable实现

    转载自: http://it.taocms.org/07/1145.htm 数据结构: HashTable数据结构的描述在Zend/zend_hash.h文件中.首先,HashTable中的每一个元素 ...

  2. 【WPF】设置ListBox容器Item的流式布局

    需求:像下图那样显示把一组内容装入ListBox中显示.要求用WrapPanel横向布局,顺序如图中的数字. 问题:ListBox默认的布局是从上往下单列的,所以需要设置布局. <ListBox ...

  3. Android——RadioGroup和CheckBox

    xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= ...

  4. KMP算法匹配原理以及C++实现

    原创作品,转载请注明出处:点我 假设A表示目标字符串,A="abababaababacb",B表示匹配模式,B="ababacb" 用两个指针i和j分别表示,A ...

  5. Windows 2008 Server搭建Radius服务器的方法

    原地址:http://service.tp-link.com.cn/detail_article_1113.html (图拷贝不过来) Windows 2008 Server搭建Radius服务器的方 ...

  6. debian配置网络

    http://blog.csdn.net/ypist/article/details/8513274 vim /etc/resolv.conf   配置域名服务器 search test.ivic.o ...

  7. Error -27740: WSA_IO_pending

    Error -27740: WSA_IO_pendingAction.c(198): Error -27791: Server **** has shut down the connection pr ...

  8. Python版本,pip版本手动管理

    http://blog.csdn.net/jiandanjinxin/article/details/53175121

  9. TensorFlow基础笔记(13) tf.name_scope tf.variable_scope学习

    转载http://blog.csdn.net/jerr__y/article/details/60877873 1. 首先看看比较简单的 tf.name_scope(‘scope_name’). tf ...

  10. 第三百一十三节,Django框架,Session

    第三百一十三节,Django框架,Session Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 1.数据库(默认)2.缓存3.文件4.缓存+数据库5.加密c ...