POJ 2155 Matrix (D区段树)
http://poj.org/problem?id=2155
|
Matrix
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 Sample Output 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区段树)的更多相关文章
- POJ 2155 Matrix(二维树状数组,绝对具体)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 20599 Accepted: 7673 Descripti ...
- poj 2155 Matrix (二维树状数组)
题意:给你一个矩阵开始全是0,然后给你两种指令,第一种:C x1,y1,x2,y2 就是将左上角为x1,y1,右下角为x2,y2,的这个矩阵内的数字全部翻转,0变1,1变0 第二种:Q x1 y1,输 ...
- POJ poj 2155 Matrix
题目链接[http://poj.org/problem?id=2155] /* poj 2155 Matrix 题意:矩阵加减,单点求和 二维线段树,矩阵加减,单点求和. */ using names ...
- POJ 2155 Matrix【二维树状数组+YY(区间计数)】
题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissio ...
- poj 2155:Matrix(二维线段树,矩阵取反,好题)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17880 Accepted: 6709 Descripti ...
- POJ 2155 Matrix (二维线段树)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17226 Accepted: 6461 Descripti ...
- poj 2155 Matrix (树状数组)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 16797 Accepted: 6312 Descripti ...
- POJ 2155 Matrix(树状数组+容斥原理)
[题目链接] http://poj.org/problem?id=2155 [题目大意] 要求维护两个操作,矩阵翻转和单点查询 [题解] 树状数组可以处理前缀和问题,前缀之间进行容斥即可得到答案. [ ...
- 【树状数组】POJ 2155 Matrix
附一篇经典翻译,学习 树状数组 http://www.hawstein.com/posts/binary-indexed-trees.html /** * @author johnsondu * @ ...
随机推荐
- Oracle表空间详解
Oracle表空间详解 1.表空间的分类 Oracle数据库把表空间分为两类:系统表空间和非系统表空间. 1.1系统表空间指的是数据库系统创建时需要的表空间,这些表空间在数据库创建时自动创建,是每个数 ...
- hdu1025 Constructing Roads In JGShining's Kingdom (nlogn的LIS)
题目链接 第一次写nlogn复杂度的LIS,纪念一下. 题目意思是说.有两条平行线.两条平行线都有n个城市,都是从左到右标记为1--n,一条线上是富有城市,一个是贫穷城市.输入n.接下来有n行,p,r ...
- PS顶级胶片滤镜插件 Alien Skin Exposure v6.x最新通用汉化补丁
Alien Skin Exposure v6.0 是一款专业的PS胶片调色滤镜软件,使用Alien Skin Exposure可以迅速将照片调出各种胶片效果,如电影胶片.宝丽来胶片效果.波拉潘胶片效果 ...
- What the difference between rebuild index and re-organize index?
avg_fragmentation_in_percent value Corrective statement > 5% and < = 30% ALTER INDEX REORGANIZ ...
- DSL简介(转)
DSL编程:有人将DSL编程称之为声明式(Declarative)编程.DSL是在模型之上建立的一种更加灵活的对 模型化的理解和使用方式.语义模型是DSL的核心.内部DSL:用通用语言的语法表示DSL ...
- linux下多进程的调试
linux下多进程的调试: (1)follow-fork-mode set follow-fork-mode [parent | child] ---- fork之后选择调试父进 ...
- Android中Dialog的使用
上一篇博文讲到对话框popWindow的使用,这篇博文主要解说Dialog的使用. 1.什么是Dialog? Dialog就是对话框的一种方式! 在Android开发中.我们常常会须要在Android ...
- Android 下拉刷新上拉载入效果功能
应用场景: 在App开发中,对于信息的获取与演示.不可能所有将其获取与演示,为了在用户使用中,给予用户以友好.方便的用户体验,以滑动.下拉的效果动态载入数据的要求就会出现. 为此.该效果功能就须要应用 ...
- 基于j2ee的程序代写MVC架构
人力资源管理系统 完成系统静态页面设计,页面数量不少于10个,页面需用CSS进行美化,并为需要验证的信息利用JavaScript提供客户端验证.要求至少包含部门信息及部门内员工信息的添加.修改.删除和 ...
- HTML5管理与实际历史的分析(history物)
HTML5新进入历史的管理,更新history对象允许国家的经营历史更方便. 在现代Web应用.用户"前进"和"退却"button切换历史页面.这使得新的页码不 ...