题目大意

给定一个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. C语言 · 最大最小值

    算法提高 题目1 最大最小值   时间限制:1.0s   内存限制:1.0GB      问题描述 给定 N 个整数,请你找出这 N 个数中最大的那个和最小的那个. 输入格式 第一行包含一个正整数 N ...

  2. 窗口过程 Wndproc

    操作系统向应用程序发送一系列消息,如左键按下和左键抬起,应用程序将通过GetMessage等方法 Wndproc应用例子最终将消息提交到窗口过程(WndProc)指向一个应用程序定义的窗口过程的指针. ...

  3. JavaScrip——练习(求整数和、求整数积)

    用HTML和JSp来实现 1.HTML调用JSp语法:<script type="text/javascript" src="整数和jsp.js"> ...

  4. 分散/聚集IO(scatter/gather)及iovec结构体

    分散/聚集 I/O是一种可以在单次系统调用中对多个缓冲区输入输出的方法,可以把多个缓冲区的数据写到单个数据流,也可以把单个数据流读到多个缓冲区中.其命名的原因在于数据会被分散到指定缓冲区向量,或者从指 ...

  5. springboot集成AOP管理日志

    如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...

  6. 谈API网关的背景、架构以及落地方案

    Chris Richardson曾经在他的博客上详细介绍过API网关,包括API网关的背景.解决方案以及案例.对于大多数基于微服务的应用程序而言,API网关都应该是系统的入口,它会负责服务请求路由.组 ...

  7. 关于Cocos2d-x中让主角运动的方法

    比如要让角色跳起来 1.如果是用到物理引擎,那么在物理世界中,可以用 hero->getPhysicsBody()->setVelocity(Vec2(0, 400));  //给主角一个 ...

  8. Asynchronous Methods for Deep Reinforcement Learning(A3C)

    Mnih, Volodymyr, et al. "Asynchronous methods for deep reinforcement learning." Internatio ...

  9. e675. 翻转缓冲图像

    // To create a buffered image, see e666 创建缓冲图像 // Flip the image vertically AffineTransform tx = Aff ...

  10. 转载:【原译】Erlang列表处理(Efficiency Guide)

    转自:http://www.cnblogs.com/futuredo/archive/2012/10/22/2734186.html List handling 1  Creating a list ...