poj2155 Matrix 二维线段树

二维线段树区间更新和单点查询,由于二维线段树不能传递标记,所以区间更新和一维不太一样,需要用到被更新的值以及更新操作的一些性质,还有要注意对query的影响。

这里操作是翻转,而且是单点查询,所以就直接在矩形块内更新,不把标记传递下去,查询的时候做一下微调,把所有经过的路径的标记都判断一遍,看是否需要翻转,这样就解决了这道题。

上一道是单点更新和区间求和,当然就不用标记了,把所有的第一维的第二层的y点全部更新,查询的时候不用查到最底层也能查到了。

二维线段树还是比较灵活,但这已经是最简单的树套树了。。。orz那些会各种线段树套平衡树,平衡树套主席树的。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

typedef long long ll;
const int maxn=1200;
const int INF=1e9+10;

int n,q;
char op[5];int x,y,xt,yt;
struct NodeY
{
    int val;
};
struct NodeX
{
    NodeY ty[maxn<<2];
    void build(int l,int r,int rt)
    {
        ty[rt].val=0;
        if(l==r) return;
        int m=(l+r)>>1;
        build(lson);
        build(rson);
    }
    void update(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            ty[rt].val^=1;
            return;
        }
        int m=(l+r)>>1;
        if(L<=m) update(L,R,lson);
        if(R>m) update(L,R,rson);
    }
    int query(int p,int l,int r,int rt)
    {
        if(l==r) return ty[rt].val;
        int m=(l+r)>>1;
        if(p<=m) return ty[rt].val^query(p,lson);
        return ty[rt].val^query(p,rson);
    }
};NodeX tx[maxn<<2];

void build(int l,int r,int rt)
{
    tx[rt].build(1,n,1);
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void update(int xL,int xR,int yL,int yR,int l,int r,int rt)
{
    if(xL<=l&&r<=xR){
        tx[rt].update(yL,yR,1,n,1);
        return;
    }
    int m=(l+r)>>1;
    if(xL<=m) update(xL,xR,yL,yR,lson);
    if(xR>m) update(xL,xR,yL,yR,rson);
}

int query(int x,int y,int l,int r,int rt)
{
    int res=tx[rt].query(y,1,n,1);
    if(l==r) return res;
    int m=(l+r)>>1;
    if(x<=m) return res^query(x,y,lson);
    return res^query(x,y,rson);
}

int main()
{
    int T;cin>>T;
    while(T--){
        scanf("%d%d",&n,&q);
        build(1,n,1);
        while(q--){
            scanf("%s",op);
            if(op[0]==‘C‘){
                scanf("%d%d%d%d",&x,&y,&xt,&yt);
                update(x,xt,y,yt,1,n,1);
            }
            else{
                scanf("%d%d",&x,&y);
                printf("%d\n",query(x,y,1,n,1));
            }
        }
        if(T) puts("");
    }
    return 0;
}

时间: 2024-08-05 10:12:02

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二维线段树

一,题意: 给你一个全为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

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