博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 1195 Mobile phones(二维树状数组)
阅读量:5224 次
发布时间:2019-06-14

本文共 1686 字,大约阅读时间需要 5 分钟。

题目链接:

题意:

  给出一个S*S的矩阵(行、列号从1开始),每个元素初始值为0,有两种操作:一种是第X行第Y列元素值加A;另一种是查询给定范围矩阵的所有元素之和(L<=X<=R,B<=Y<=T)。

分析:

  查询给定范围矩阵的所有元素之和是二维区间和,可以转换为二维前缀和求值。类比一维前缀和求法,二维区间和S(L, B, R, T) = S(1, 1, R, T) - S(1 ,1, L-1, T) - S(1, 1, R, B-1) + S(1, 1, L-1, B-1)。单点更新一个元素的值,修改二维前缀和,类比一维树状数组的更新操作,二维树状数组的更新操作(参考代码)。

总结:

  二维树状数组可以理解为:先固定X=i,把Y=1~S看作一维树状数组就比较容易理解,再X=1~S看作一维树状数组,这样组合成二维树状数组。如果还想不明白,可以想想二元积分是怎么做的。

代码实现:

#include 
#include
#include
#include
#include
using namespace std;const int N = 1024 + 5;int C[N][N], cmd, s, x, y, a, l, b, r, t;int lowbit(int x){ return x & (-x);}void add(int x, int y, int a){ for (int i = x; i <= s; i += lowbit(i)) for (int j = y; j <= s; j += lowbit(j)) C[i][j] += a;}int sum(int x, int y){ int ret = 0; for (int i = x; i; i -= lowbit(i)) for (int j = y; j; j -= lowbit(j)) ret += C[i][j]; return ret;}int main(){ while (~scanf("%d", &cmd)) { if (cmd == 3) break; if (cmd == 0) { scanf("%d", &s); for (int i = 1; i <= s; i++) for (int j = 1; j <= s; j++) C[i][j] = 0; continue; } if (cmd == 1) { scanf("%d%d%d", &x, &y, &a); x++, y++; add(x, y, a); continue; } if (cmd == 2) { scanf("%d%d%d%d", &l, &b, &r, &t); l++, b++, r++, t++; int ans = sum(r, t) - sum(l-1, t) - sum(r, b-1) + sum(l-1, b-1); printf("%d\n", ans); } } return 0;}

  

转载于:https://www.cnblogs.com/From-scratch/p/7361850.html

你可能感兴趣的文章
NoSQL数据库常见分类
查看>>
一题多解 之 Bat
查看>>
Java 内部类
查看>>
{面试题7: 使用两个队列实现一个栈}
查看>>
【练习】使用事务和锁定语句
查看>>
centos7升级firefox的flash插件
查看>>
Apache Common-IO 使用
查看>>
再谈Vmware NAT的配置和路由流程
查看>>
javaScript数组去重方法汇总
查看>>
评价意见整合
查看>>
二、create-react-app自定义配置
查看>>
Android PullToRefreshExpandableListView的点击事件
查看>>
系统的横向结构(AOP)
查看>>
linux常用命令
查看>>
NHibernate.3.0.Cookbook第四章第6节的翻译
查看>>
例1-1
查看>>
马达调速器,直流马达调速器,直流调速器
查看>>
前端编码规范小记
查看>>
c如何弹出保存路径/保存文件对话框
查看>>
HTML标签二
查看>>