http://poj.org/problem?id=2155

Matrix
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 18143   Accepted: 6813

Description

Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N). 



We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change
it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions. 



1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2). 

2. Q x y (1 <= x, y <= n) querys A[x, y]. 

Input

The first line of the input is an integer X (X <= 10) representing the number of test cases. The following X blocks each represents a test case. 



The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2
y2", which has been described above. 

Output

For each querying output one line, which has an integer representing A[x, y]. 



There is a blank line between every two continuous test cases. 

Sample Input

1
2 10
C 2 1 2 2
Q 2 2
C 2 1 2 1
Q 1 1
C 1 1 2 1
C 1 2 1 2
C 1 1 2 2
Q 1 1
C 1 1 2 1
Q 2 1

Sample Output

1
0
0
1

Source

POJ Monthly,Lou Tiancheng

谨以此题来祭我的第一道二维线段树!

没有30道线段树的基础不要碰二维线段树。

题意:

给出一个N×N的零矩阵。有两种操作:C x1 y1 x2 y2 是将(x1,y1) (x2,y2)相应范围内的矩阵中的0/1互换,Q x y是查询(x,y)位置元素的值。

分析:

0/1互换即异或操作,朴素的算法时间复杂度显然不够。假设是一维的坐标轴显然能够用线段树解,但这是一个二维的。那么就要用到二维线段树了。

以前的我天真地觉得二维线段树就是把一个矩形直接分成4份:左上、右上、左下、右下,后来遇到一个三维的题目我还YY出了把立方体分成8份来解(当然没过啦,并且标程也不是用线段树的)。

实际上,二维线段树是先将X坐标二分,然后再将Y轴二分。

第二维维护的也是一棵线段树,没错。二维线段树就是线段树套线段树!二分。再二分!

本题每次更新的时候先操作X轴,操作到相应区间时再对Y轴进行操作,从二维到一维。达到降维的效果。

查询时每次查到在所在的X区间内时都要对Y轴进行查询。

假设对线段树理解较深。相信对此不难理解。

详情请见代码(个人习惯维护左闭右开的区间,下标从0開始,所以有些调整):

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm
#define maxn 1007 using namespace std; int XOR[maxn<<2][maxn<<2];
int n,m; //update_1d() 更新一维
//[a,b)表示当前在一维操作的区间(Y方向)。k为节点标号,[l,r)表示节点相应维护的区间(Y方向),k_2d表示二维相应的节点标号
void update_1d(int a,int b,int k,int l,int r,int k_2d)
{
if (b<=l || r<=a) return ;
if (a<=l && r<=b)
{
XOR[k_2d][k]^=1;
}
else
{
update_1d(a,b,k*2+1,l,l+r>>1,k_2d);
update_1d(a,b,k*2+2,l+r>>1,r,k_2d);
}
} //update_2d() 更新二维
//[a,b)表示当前在二维操作的区间(X方向)。[y1,y2)表示将要在一维操作的区间(Y方向),k为节点标号,[l,r)表示节点相应维护的区间(X方向)
void update_2d(int a,int b,int y1,int y2,int k,int l,int r)
{
if (b<=l || r<=a) return ;
if (a<=l && r<=b)
{
update_1d(y1,y2,0,0,n,k);
}
else
{
update_2d(a,b,y1,y2,k*2+1,l,l+r>>1);
update_2d(a,b,y1,y2,k*2+2,l+r>>1,r);
}
} //query_1d() 查询一维
//p表示当前在一维查询的位置(Y方向),k为节点标号,[l,r)表示节点相应维护的区间(Y方向),k_2d表示二维相应的节点标号
int query_1d(int p,int k,int l,int r,int k_2d)
{
if (r-l==1) return XOR[k_2d][k]; int m=l+r>>1; if (p<m)
return XOR[k_2d][k]^query_1d(p,k*2+1,l,m,k_2d);
else
return XOR[k_2d][k]^query_1d(p,k*2+2,m,r,k_2d);
} //query_2d() 查询二维
//px表示当前在二维查询的位置(X方向),py表示将要在一维查询的位置(Y方向),k为节点标号。[l,r)表示节点相应维护的区间(X方向)
int query_2d(int px,int py,int k,int l,int r)
{
int res=query_1d(py,0,0,n,k);// attention please! if (r-l==1) return res; int m=l+r>>1; if (px<m)
return res^query_2d(px,py,k*2+1,l,m);
else
return res^query_2d(px,py,k*2+2,m,r);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("/home/fcbruce/文档/code/t","r",stdin);
#endif // ONLINE_JUDGE int T_T;
scanf("%d",&T_T); while (T_T--)
{ scanf("%d %d",&n,&m);
memset(XOR,0,sizeof XOR); for (int i=0;i<m;i++)
{
char op;
int x1,x2,y1,y2; getchar();
op=getchar(); if (op=='C')
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
x1--;y1--;
update_2d(x1,x2,y1,y2,0,0,n);
}
else
{
scanf("%d %d",&x1,&y1);
x1--;y1--;
printf("%d\n",query_2d(x1,y1,0,0,n));
}
} if (T_T) putchar('\n'); //由于这个PE一发
} return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

POJ 2155 Matrix (D区段树)的更多相关文章

  1. POJ 2155 Matrix(二维树状数组,绝对具体)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20599   Accepted: 7673 Descripti ...

  2. poj 2155 Matrix (二维树状数组)

    题意:给你一个矩阵开始全是0,然后给你两种指令,第一种:C x1,y1,x2,y2 就是将左上角为x1,y1,右下角为x2,y2,的这个矩阵内的数字全部翻转,0变1,1变0 第二种:Q x1 y1,输 ...

  3. POJ poj 2155 Matrix

    题目链接[http://poj.org/problem?id=2155] /* poj 2155 Matrix 题意:矩阵加减,单点求和 二维线段树,矩阵加减,单点求和. */ using names ...

  4. POJ 2155 Matrix【二维树状数组+YY(区间计数)】

    题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissio ...

  5. poj 2155:Matrix(二维线段树,矩阵取反,好题)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17880   Accepted: 6709 Descripti ...

  6. POJ 2155 Matrix (二维线段树)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17226   Accepted: 6461 Descripti ...

  7. poj 2155 Matrix (树状数组)

    Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16797   Accepted: 6312 Descripti ...

  8. POJ 2155 Matrix(树状数组+容斥原理)

    [题目链接] http://poj.org/problem?id=2155 [题目大意] 要求维护两个操作,矩阵翻转和单点查询 [题解] 树状数组可以处理前缀和问题,前缀之间进行容斥即可得到答案. [ ...

  9. 【树状数组】POJ 2155 Matrix

    附一篇经典翻译,学习 树状数组  http://www.hawstein.com/posts/binary-indexed-trees.html /** * @author johnsondu * @ ...

随机推荐

  1. Oracle表空间详解

    Oracle表空间详解 1.表空间的分类 Oracle数据库把表空间分为两类:系统表空间和非系统表空间. 1.1系统表空间指的是数据库系统创建时需要的表空间,这些表空间在数据库创建时自动创建,是每个数 ...

  2. hdu1025 Constructing Roads In JGShining&#39;s Kingdom (nlogn的LIS)

    题目链接 第一次写nlogn复杂度的LIS,纪念一下. 题目意思是说.有两条平行线.两条平行线都有n个城市,都是从左到右标记为1--n,一条线上是富有城市,一个是贫穷城市.输入n.接下来有n行,p,r ...

  3. PS顶级胶片滤镜插件 Alien Skin Exposure v6.x最新通用汉化补丁

    Alien Skin Exposure v6.0 是一款专业的PS胶片调色滤镜软件,使用Alien Skin Exposure可以迅速将照片调出各种胶片效果,如电影胶片.宝丽来胶片效果.波拉潘胶片效果 ...

  4. What the difference between rebuild index and re-organize index?

    avg_fragmentation_in_percent value Corrective statement > 5% and < = 30% ALTER INDEX REORGANIZ ...

  5. DSL简介(转)

    DSL编程:有人将DSL编程称之为声明式(Declarative)编程.DSL是在模型之上建立的一种更加灵活的对 模型化的理解和使用方式.语义模型是DSL的核心.内部DSL:用通用语言的语法表示DSL ...

  6. linux下多进程的调试

    linux下多进程的调试:  (1)follow-fork-mode           set follow-fork-mode [parent | child] ---- fork之后选择调试父进 ...

  7. Android中Dialog的使用

    上一篇博文讲到对话框popWindow的使用,这篇博文主要解说Dialog的使用. 1.什么是Dialog? Dialog就是对话框的一种方式! 在Android开发中.我们常常会须要在Android ...

  8. Android 下拉刷新上拉载入效果功能

    应用场景: 在App开发中,对于信息的获取与演示.不可能所有将其获取与演示,为了在用户使用中,给予用户以友好.方便的用户体验,以滑动.下拉的效果动态载入数据的要求就会出现. 为此.该效果功能就须要应用 ...

  9. 基于j2ee的程序代写MVC架构

    人力资源管理系统 完成系统静态页面设计,页面数量不少于10个,页面需用CSS进行美化,并为需要验证的信息利用JavaScript提供客户端验证.要求至少包含部门信息及部门内员工信息的添加.修改.删除和 ...

  10. HTML5管理与实际历史的分析(history物)

    HTML5新进入历史的管理,更新history对象允许国家的经营历史更方便. 在现代Web应用.用户"前进"和"退却"button切换历史页面.这使得新的页码不 ...