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. hdu 4771 Stealing Harry Potter&#39;s Precious

    题目:给出一个二维图,以及一个起点,m个中间点,求出从起点出发,到达每一个中间的最小步数. 思路:由于图的大小最大是100*100,所以要使用bfs求出当中每两个点之间的最小距离.然后依据这些步数,建 ...

  2. Android 性能优化 五 性能分析工具dumpsys的使用

    Android提供的dumpsys工具能够用于查看感兴趣的系统服务信息与状态,手机连接电脑后能够直接命令行运行adb shell dumpsys 查看全部支持的Service可是这样输出的太多,能够通 ...

  3. 分布式Unique ID的生成方法

    分布式Unique ID的生成方法 分布式的Unique ID的用途如此广泛,从业务对象Id到日志的TraceId,本文总结了林林总总的各种生成算法. 1. 发号器 我接触的最早的Unique ID, ...

  4. Java EE (12) -- 系统质量的分类

    明显的 性能(Performance): 对响应用户的应答时间的度量.可靠性(Reliability): 对包括后台存储和给用户的表示结果在内的数据正确的可能性的度量.可用性(Availability ...

  5. MySQL 改动用户password及重置rootpassword

    为数据库用户改动password是DBA比較常见的工作之中的一个.对于MySQL用户账户的password改动,有几种不同的方式.推荐的方式使用加密函数来改动password. 本文主要描写叙述了通过 ...

  6. Custom Media Player in WPF (Part 1)

    First of all I would like to welcome everyone to my new blog and wish you all a happy new year… Thro ...

  7. volatile解析(转)

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  8. APUE学习总结

    简介 本文总结了个人,一个数字,对应称号<APUE>第一版的每一章,但是,独立的二级标题和书,人需求进行编写. 3.文件I/O 本章所说明的函数常常被称之为不带缓存的I/O(与第5章中说明 ...

  9. 64位内核注冊tty设备

    在64位系统中,注冊tty设备须要注意的是,Android跑在EL0而且在32位模式下,kernel跑在EL1而且在64位模式下,不但内核须要打开CONFIG_COMPAT选项,非常多android上 ...

  10. Android Application Thread CPU GC Operatiing and OOM Question 0603-随手笔记

    面前app当完成测试,没问题,以完成整个老龄化阶段包含数据收发器,关键在 adb shell top -m 5  我发现我的 app pid 占用  CPU是最多的,事实上我想说写一个app是不难,你 ...