POJ2155 二维树状数组求区域和
2016-03-19 22:05
288 查看
题意 : 有一个N*N 的网格,X组测试样例,一开始网格之中的数全为 0 。输入一个操作数 T,有两种操作,C代表修改,意思是将 (X1,Y1)和(X2,Y2)围成一个矩形区域中的数全部取“非”(即原本是0的变成1,原本是1的改为0)。Q代表查询,意思是查询(X,Y)网格中的数字。
对于这道题一开始想到的是二维线段树的区间更新,但写起来麻烦,后来想到了一个巧妙的思想:对于网格中的数字,我们只需要知道它的修改次数就可以了,但是如果不用区间更新的话就会超时,原因是N * N * T的复杂度,其实如果只去标记被围住的区间的几个必要点就可以了。举个一维的例子来看,如果要修改(X,Y)区间的数字,那么只需要将 X 点和 Y+1 点处加1 就可以了,这样再询问某个点数字的时候,1到 该点 的和就是我们对这个数字修改过的次数。 二维的情况参照一维并扩展成四个点就好。而树状数组正是实现数组 1-n 处求和的好方式。
代码如下:
对于这道题一开始想到的是二维线段树的区间更新,但写起来麻烦,后来想到了一个巧妙的思想:对于网格中的数字,我们只需要知道它的修改次数就可以了,但是如果不用区间更新的话就会超时,原因是N * N * T的复杂度,其实如果只去标记被围住的区间的几个必要点就可以了。举个一维的例子来看,如果要修改(X,Y)区间的数字,那么只需要将 X 点和 Y+1 点处加1 就可以了,这样再询问某个点数字的时候,1到 该点 的和就是我们对这个数字修改过的次数。 二维的情况参照一维并扩展成四个点就好。而树状数组正是实现数组 1-n 处求和的好方式。
代码如下:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn=1e3+5; int bit[maxn][maxn]; int n,q; int sum(int x,int y){ int s=0; for(int i=x;i>0;i-=(i&-i)){ for(int j=y;j>0;j-=(j&-j)){ s+=bit[i][j]; } } return s; } void add(int x,int y,int v){ for(int i=x;i<=n;i+=(i&-i)){ for(int j=y;j<=n;j+=(j&-j)){ bit[i][j]+=v; } } } int main() { //ios::sync_with_stdio(false); int T; cin>>T; while(T--){ memset(bit,0,sizeof(bit)); cin>>n>>q; while(q--){ char temp[2]; scanf("%s",temp); if(temp[0]=='Q'){ int x,y; char k; scanf("%d %d",&x,&y); int s=sum(x,y); if(s & 1) cout<<"1"<<endl; else cout<<"0"<<endl; } if(temp[0]=='C'){ int x1,y1,x2,y2; char k; scanf("%d %d %d %d",&x1,&y1,&x2,&y2); add(x1,y1,1); add(x1,y2+1,1); add(x2+1,y1,1); add(x2+1,y2+1,1); } } cout<<endl; } //system("pause"); return 0; }
相关文章推荐
- NIIT实训 java笔记--3.11
- HTML5 - Voide标签
- ExtJs之文本框及数字输入
- Tornado模块分类和各模块之间的关系
- LeetCode – 3Sum — 题解
- 简单html代码标签
- 用Python+Django在Eclipse环境下开发web网站
- 注意转发和重定向的区别
- 利用JQuery实现广告动态滚动特效
- jQuery学习笔记(3)-操作jQuery包装集的函数
- 第三周作业
- HDU 2057 A + B Again
- Java网络编程之NIO编程(待补充)
- 递归算法实例
- Hadoop调优
- Struts和Hibernate整合中分页实现解析
- 插入排序(链表)
- PSR-2 Coding Style Guide
- 双向循环链表
- ReactiveCocoa学习总结