题目大意

给定一个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#】遍历List列表的同时,移除访问到的元素

    需求:遍历List列表,当访问的元素符合某一条件时,将该元素移除出列表. 注意点:使用foreach循环遍历无法做到边读边修改,所以要使用for循环. 例子: // 倒序遍历. for (int i ...

  2. C语言 · 报时助手

    基础练习 报时助手   时间限制:1.0s   内存限制:512.0MB          锦囊1 判断,字符串输出. 锦囊2 按要求输出,判断特殊情况.   问题描述 给定当前的时间,请用英文的读法 ...

  3. 无法识别的属性 configProtectionProvider的解决方案

    用RsaProtectedConfigurationProvider加密数据库连接字符串时,只要App.config有任何改动,都会提示无法识别的属性 configProtectionProvider ...

  4. java多线程有几种实现方法?线程之间如何同步

    java中多线程的实现方法有两种:1.直接继承thread类:2.实现runnable接口: 同步的实现方法有五种:1.同步方法:2.同步代码块:3.使用特殊域变量(volatile)实现线程同步:4 ...

  5. Axel 快速下载

    Axel 是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载. Axel 支持 HTTP.HTTPS.FTP 和 FTPS 协议.它也可以使 ...

  6. vlan pvid vid access口 trunk口

    VLAN技术浅谈    http://www.h3c.com.cn/MiniSite/H3care_Club/Data_Center/Net_Reptile/The_One/Home/Catalog/ ...

  7. java笔记知识点总结

    1.switch case default 语句 : switch case 语句是一个条件选择语句,找到相同的case值做为入口,执行后面的程序:若所有的case都不满足,则找default入口:若 ...

  8. Graying the black box: Understanding DQNs

    Zahavy, Tom, Nir Ben-Zrihem, and Shie Mannor. "Graying the black box: Understanding DQNs." ...

  9. C++异常抛出与捕获及处理

    一.异常 迄今为止,我们处理程序中的错误一般都是用if语句测试某个表达式,然后处理错误的特定义代码. C++异常机制使用了三个新的关键字  (SEH(结构化异常处理)) try    ──标识可能出现 ...

  10. maven 打包可执行jar的两种方法

    1.修改pom.xml增加如下内容 <build> <pluginManagement> <plugins> <plugin> <groupId& ...