POJ2155 Matrix二维线段树

一,题意:

给你一个全为0的N * N的矩阵,对这个矩阵有两个操作(对于矩阵只有两个状态0,1)

(1):“C x1,y1,x2,y2”   就是将左上角为x1,y1,右下角为x2,y2,的这个矩阵内的数字全部翻转。

(2):“Q x1 y1”   输出a[x1][y1]的值。

二,解析:

该我主要应用令二位的树状数组,一个是行,一个是列。

三,代码:

#include<iostream>
#include<cstdio>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int Max=1002;
int Mat[Max][Max];
//Mat[i][j] 表示(i,j)到(n,n)区间改变次数
int N,T,X;
char str;
int step(int x)
{
    return x&(-x);
}
int sum(int x,int y)
{//包含点(x,y)取区间改变次数和即(0.0)到(x,y)区间和;
    int total=0;
    for(int i=x; i>0; i-=step(i))
        for(int j=y; j>0; j-=step(j))
            total+=Mat[i][j];
    return total;
}
void change(int x,int y)
{//将(x,y)到(n,n)区间反转增加一次
    for(int i=x; i<=N; i+=step(i))
        for(int j=y; j<=N; j+=step(j))
            Mat[i][j]++;
}

int main()
{
    scanf("%d",&X);
    while(X--)
    {
        scanf("%d%d",&N,&T);
        memset(Mat,0,sizeof(Mat));
        while(T--)
        {
            getchar();
            scanf("%c",&str);
            if(str=='C')
            {
                int x_1,y_1,x_2,y_2;
                scanf("%d%d%d%d",&x_1,&y_1,&x_2,&y_2);
                change(x_1,y_1);
                change(x_1,y_2+1);
                change(x_2+1,y_1);
                change(x_2+1,y_2+1);
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                int key=sum(x,y);
                printf("%d\n",key%2);
            }
        }
        printf("\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 01:38:41

POJ2155 Matrix二维线段树的相关文章

POJ2155 Matrix二维线段树经典题

题目链接 二维树状数组 1 #include<iostream> 2 #include<math.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 using namespace std; 6 #define ll long long 7 #define re(i,n) for(int i=0;i<n;i++) 8 const int maxn = 1007; 9 int c[maxn][maxn]; 10

poj2155 Matrix 二维线段树

二维线段树区间更新和单点查询,由于二维线段树不能传递标记,所以区间更新和一维不太一样,需要用到被更新的值以及更新操作的一些性质,还有要注意对query的影响. 这里操作是翻转,而且是单点查询,所以就直接在矩形块内更新,不把标记传递下去,查询的时候做一下微调,把所有经过的路径的标记都判断一遍,看是否需要翻转,这样就解决了这道题. 上一道是单点更新和区间求和,当然就不用标记了,把所有的第一维的第二层的y点全部更新,查询的时候不用查到最底层也能查到了. 二维线段树还是比较灵活,但这已经是最简单的树套树

POJ 2155 Matrix (二维线段树)

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. I

POJ 2155 Matrix 二维线段树+标记永久化?

题意:链接 方法:二维线段树+标记永久化 解析:题意是比较明朗的,算一下内存发现4000^2也是可以接受的,于是就开始yy二维线段树? 对于第一层x的线段树,每个节点开一整棵y线段树. 用个二维数组就实现了? 不过发现个问题啊,这题怎么pushdown啊,标记传不下去啊.如果给x打个标记那么怎么知道y传那段啊? 于是就学了新的东西?标记永久化. 本题是单点查询嘛,标记永久化就应该是把相应的区间直接异或,不用往下传?那查询的时候怎么办呢?只需要在查询的时候把所有路过该点的区间都异或起来就OK了.貌

[POJ2155] Matrix(二维线段树,树套树)

题目链接:http://poj.org/problem?id=2155 题意:给一个01矩阵,两个操作,翻转:子矩阵里每一个数都由0变1,1变0. 查询:查询某一点是0还是1. 一直以为二维线段树就是开一个线段树数组的我- 这题暴力更新每一个小矩形,翻转就+1,最后看看某点的奇偶. 写屎了,特别注意的是在外层查询的时候要先把当前层的内层query掉,接着再向下扩展.这样外层就不用lazy啦 1 #include <algorithm> 2 #include <iostream> 3

ZOJ 1859 Matrix Searching(二维线段树)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1859 Matrix Searching Time Limit: 10 Seconds      Memory Limit: 32768 KB Given an n*n matrix A, whose entries Ai,j are integer numbers ( 1 <= i <= n, 1 <= j <= n ). An operation FIND t

[poj2155]Matrix(二维树状数组)

Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25004   Accepted: 9261 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

POJ2155 Matrix 二维树状数组的应用

有两种方法吧,一个是利用了树状数组的性质,很HDU1556有点类似,还有一种就是累加和然后看奇偶来判断答案 题意:给你一个n*n矩阵,然后q个操作,C代表把以(x1,y1)为左上角到以(x2,y2)为右下角的矩阵取反,意思就是矩阵只有0,1元素,是0的变1,是1的变0,Q代表当前(x,y)这个点的状况,是0还是1? 区间修改有点特别,但是若区间求和弄懂了应该马上就能懂得: add(x2,y2,1); add(x2,y1,-1);//上面多修改了不需要的一部分,所以修改回来 add(x1,y2,-

POJ 2155 Matrix【二维线段树】

题目大意:给你一个全是0的N*N矩阵,每次有两种操作:1将矩阵中一个子矩阵置反,2.查询某个点是0还是1 思路:裸的二维线段树 #include<iostream>#include<cstdio>#include <math.h>#include<algorithm>#include<string.h>#include<queue>#define MOD 1000003#define maxn 4009#define LL long