poj_1190 树状数组
题目大意
给定一个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 树状数组的更多相关文章
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
		
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2221 Solved: 1179[Submit][Sta ...
 - bzoj1878--离线+树状数组
		
这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...
 - codeforces 597C C. Subsequences(dp+树状数组)
		
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
 - BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
		
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
 - BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]
		
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1399 Solved: 694[Submit][Status] ...
 - BZOJ 3289: Mato的文件管理[莫队算法 树状数组]
		
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2399 Solved: 988[Submit][Status][Di ...
 - 【Codeforces163E】e-Government     AC自动机fail树 + DFS序 + 树状数组
		
E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
 - 【BZOJ-3881】Divljak      AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
		
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
 - 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
		
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
 
随机推荐
- Linux 下 ps 命令
			
简述 Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,动态的显示进程信息 ...
 - 【分区助手】如何扩大C盘容量?
			
问题:C盘容量太小,想通过缩小其他盘(比如本例的F盘)来扩大C盘. 工具:分区助手 步骤: 1.下好分区助手后打开(该软件建议装在C盘),选择左侧的[扩大分区导向]. 2.选择下面那个,要先缩小F盘扩 ...
 - VC++中动态链接库的显示加载和隐式加载的区别
			
两种方法对于你的程序调用动态库时没有任何区别,只是你在编程时,步骤是不一样的.显式调用麻烦了点,但可以没有相应的lib库:隐式调用,使用起来比较 简单,有函数的声明(头文件.h)就可以了,但必须有li ...
 - [转]eclipse导入V7包出现错误解决办法
			
android下v4 v7 v21等包是android系统的扩展支持包,就想windows的系统补丁一个道理. android的扩展包主要是用来兼容低版本的,比如android3.0以后出现 ...
 - hive thrift 开机启动
			
这个问题困扰我很久,之前redis的时候,也出现了这个问题,从网上找的thrift脚本没有一个好使的,最后通过修改/etc/rc.d/rc.local来执行一些非服务的命令,这样子就不需要像写服务那样 ...
 - DataRowState、AcceptChanges、RejectChanges综合使用示例:实现DataGridView数据的增、删、改
			
下面的示例中,通过一个程序,演示使用DataRowState.AcceptChanges.RejectChanges,实现DataGridView数据的增.删.改. 一.界面设计 二.代码实现 usi ...
 - Ajax-ajax实例1-动态加载的 FAQ
			
动态加载 FAQ 的过程主要是利用 XMLHttpRequest(以下简称 XHR)对象与服务端通信,根据用户单击的感兴趣问题动态将内容加载到页面中.在具体实现时,有两点要注意的内容. 1 .对每个问 ...
 - linux访问ftp服务器命令
			
在linux访问时输入 用户名 anonymous 密码直接回车可以匿名登录 如果传输非文本,先输入bianry,然后再get就可以了 比如 ftp> get 5-4.tif 227 Enter ...
 - 商务导航路由配置 2——端口映射 内网通过公网IP访问设置
 - Message Code 【27796】 Failed to connect to server 'hostname';port_ld': 'reason'.
			
Message Code [27796] Failed to connect to server 'hostname';port_ld': 'reason'.Unable to connect to ...