[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 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 using namespace std;
 19
 20 #define lrt rt << 1
 21 #define rrt rt << 1 | 1
 22 const int maxn = 1010;
 23
 24 typedef struct NodeY {
 25     int val, sign;
 26 }NodeY;
 27
 28 typedef struct NodeX {
 29     NodeY segY[maxn<<2];
 30
 31     void build(int l, int r, int rt) {
 32         segY[rt].val = segY[rt].sign = 0;
 33         if(l == r) return;
 34         int mid = (l + r) >> 1;
 35         build(l, mid, lrt);
 36         build(mid+1, r, rrt);
 37     }
 38
 39     void pushdown(int l, int r, int rt) {
 40         if(segY[rt].sign) {
 41             int mid = (l + r) >> 1;
 42             segY[lrt].sign += segY[rt].sign;
 43             segY[rrt].sign += segY[rt].sign;
 44              segY[lrt].val += (mid - l + 1) * segY[rt].sign;
 45             segY[rrt].val += (r - mid) * segY[rt].sign;
 46             segY[rt].sign = 0;
 47         }
 48     }
 49
 50     void update(int L, int R, int l, int r, int rt) {
 51         if(L <= l && r <= R) {
 52             segY[rt].sign++;
 53             segY[rt].val += (r - l + 1);
 54             return;
 55         }
 56         pushdown(l, r, rt);
 57         int mid = (l + r) >> 1;
 58         if(L <= mid) update(L, R, l, mid, lrt);
 59         if(mid < R) update(L, R, mid+1, r, rrt);
 60     }
 61
 62     int query(int pos, int l, int r, int rt) {
 63         if(l == r) return segY[rt].val;
 64         pushdown(l, r, rt);
 65         int mid = (l + r) >> 1;
 66         int ret = 0;
 67         if(pos <= mid) ret += query(pos, l, mid, lrt);
 68         else ret += query(pos, mid+1, r, rrt);
 69         return ret;
 70     }
 71 }NodeX;
 72
 73 int n, q;
 74 NodeX segX[maxn<<2];
 75
 76 void build(int l, int r, int rt) {
 77     segX[rt].build(1, n, 1);
 78     if(l == r) return;
 79     int mid = (l + r) >> 1;
 80     build(l, mid, lrt);
 81     build(mid+1, r, rrt);
 82 }
 83
 84 void update(int yl, int yr, int L, int R, int l, int r, int rt) {
 85     if(L <= l && r <= R) {
 86         segX[rt].update(yl, yr, 1, n, 1);
 87         return;
 88     }
 89     int mid = (l + r) >> 1;
 90     if(L <= mid) update(yl, yr, L, R, l, mid, lrt);
 91     if(mid < R) update(yl, yr, L, R, mid+1, r, rrt);
 92 }
 93
 94 int query(int x, int y, int l, int r, int rt) {
 95     int ret = segX[rt].query(y, 1, n, 1);
 96     if(l == r) return ret;
 97     int mid = (l + r) >> 1;
 98     if(x <= mid) ret += query(x, y, l, mid, lrt);
 99     else ret += query(x, y, mid+1, r, rrt);
100     return ret;
101 }
102
103 char op[3];
104 int xa, ya, xb, yb;
105
106 int main() {
107     // freopen("in", "r", stdin);
108     int T;
109     scanf("%d", &T);
110     while(T--) {
111         scanf("%d%d",&n,&q);
112         build(1, n, 1);
113         while(q--) {
114             scanf("%s", op);
115             if(op[0] == ‘C‘) {
116                 scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
117                 update(ya, yb, xa, xb, 1, n, 1);
118             }
119             else {
120                 scanf("%d%d",&xa,&ya);
121                 printf("%d\n", query(xa, ya, 1, n, 1) % 2);
122             }
123         }
124         printf("\n");
125     }
126     return 0;
127 }

按位翻转也可以,不过要加个pushdown:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 using namespace std;
 19
 20 #define lrt rt << 1
 21 #define rrt rt << 1 | 1
 22 const int maxn = 1010;
 23
 24 typedef struct NodeY {
 25     bool sign;
 26 }NodeY;
 27
 28 typedef struct NodeX {
 29     NodeY segY[maxn<<2];
 30     void build(int l, int r, int rt) {
 31         segY[rt].sign = 0;
 32         if(l == r) return;
 33         int mid = (l + r) >> 1;
 34         build(l, mid, lrt);
 35         build(mid+1, r, rrt);
 36     }
 37     void pushdown(int rt) {
 38         if(segY[rt].sign) {
 39             segY[lrt].sign ^= 1; segY[rrt].sign ^= 1;
 40             segY[rt].sign = 0;
 41         }
 42     }
 43     void update(int L, int R, int l, int r, int rt) {
 44         if(L <= l && r <= R) {
 45             segY[rt].sign ^= 1;
 46             return;
 47         }
 48         pushdown(rt);
 49         int mid = (l + r) >> 1;
 50         if(L <= mid) update(L, R, l, mid, lrt);
 51         if(mid < R) update(L, R, mid+1, r, rrt);
 52     }
 53     int query(int pos, int l, int r, int rt) {
 54         if(l == r) return segY[rt].sign;
 55         pushdown(rt);
 56         int mid = (l + r) >> 1;
 57         if(pos <= mid) return query(pos, l, mid, lrt);
 58         else return query(pos, mid+1, r, rrt);
 59     }
 60 }NodeX;
 61
 62 int n, q;
 63 NodeX segX[maxn<<2];
 64
 65 void build(int l, int r, int rt) {
 66     segX[rt].build(1, n, 1);
 67     if(l == r) return;
 68     int mid = (l + r) >> 1;
 69     build(l, mid, lrt);
 70     build(mid+1, r, rrt);
 71 }
 72
 73 void update(int yl, int yr, int L, int R, int l, int r, int rt) {
 74     if(L <= l && r <= R) {
 75         segX[rt].update(yl, yr, 1, n, 1);
 76         return;
 77     }
 78     int mid = (l + r) >> 1;
 79     if(L <= mid) update(yl, yr, L, R, l, mid, lrt);
 80     if(mid < R) update(yl, yr, L, R, mid+1, r, rrt);
 81 }
 82
 83 int query(int x, int y, int l, int r, int rt) {
 84     int ret = segX[rt].query(y, 1, n, 1);
 85     if(l == r) return ret;
 86     int mid = (l + r) >> 1;
 87     if(x <= mid) ret ^= query(x, y, l, mid, lrt);
 88     else ret ^= query(x, y, mid+1, r, rrt);
 89     return ret;
 90 }
 91
 92 char op[3];
 93 int xa, ya, xb, yb;
 94
 95 int main() {
 96     // freopen("in", "r", stdin);
 97     int T;
 98     scanf("%d", &T);
 99     while(T--) {
100         scanf("%d%d",&n,&q);
101         build(1, n, 1);
102         while(q--) {
103             scanf("%s", op);
104             if(op[0] == ‘C‘) {
105                 scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
106                 update(ya, yb, xa, xb, 1, n, 1);
107             }
108             else {
109                 scanf("%d%d",&xa,&ya);
110                 printf("%d\n", query(xa, ya, 1, n, 1));
111             }
112         }
113         printf("\n");
114     }
115     return 0;
116 }
时间: 2024-12-26 14:14:49

[POJ2155] Matrix(二维线段树,树套树)的相关文章

poj2155 Matrix 二维线段树

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

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

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,-

[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

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

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

POJ2155 Matrix 二维树状数组应用

一个N*N(1<=N<=1000)的矩阵,从(1,1)开始,给定一些操作C和一些查询Q,一共K条(1<=K<=50000): C x1,y1,x2,y2 表示从x1行y1列到x2行y2列的元素全部反转(0变成1,1变成0): Q x y表示询问x行y列的元素是0还是1. 题目乍一看感觉还是很难,如果能记录每一个元素的状态值,那答案是显而易见的,但是元素过多,如果每次都对每一个元素进行更新状态的话,复杂度太高.实际上只要记录边界的特定坐标的反转次数,最好的选择那就是二维树状数组了.

poj2155 Matrix 二维数组数组

http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 18769   Accepted: 7078 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

POJ2155: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 upp