POJ - 2155
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 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 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 题目意思是给你一个矩阵,最開始都是为0,然后给你一个左上角的坐标,右下角的坐标,将这个区域的0 -> 1,1 -> 0,然后给你一个点让你求出他此时的结果是1还是0. 这里能够用树状数组的区间改动以及单点求值。仅仅是这里是二维的树状数组,原理是一样的。 将其改变的话,能够如此,如果最開始[1....x2][1....y2]为偶数的话(这里就是看成是前辍和) 先将[1....x2][1....y2]添加1,变为奇数,然后将[1...x1 - 1][y2]添加1变为偶数,将[1....x2][y1]添加1变为偶数,而他们中间重叠的[1....x1 - 1][1....x2 - 1]部分则是被改变了三次。还是奇数,所以还有加1。将他变为偶数,如此除了[x1....x2][y1....y2]变了外。其它的地方依然没有改变。 /* Author: 2486 Memory: 4304 KB Time: 547 MS Language: G++ Result: Accepted */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1000 + 5; int C[MAXN][MAXN]; int N, X, M, x, y, x1, x2, y1, y2; char op[10]; int lowbits(int x){ return x & (-x); } void add(int x,int y){ for(int i = x; i <= N;i += lowbits(i)){ for(int j = y;j <= N;j += lowbits(j)){ C[i][j] ++; } } } int query(int x,int y){ int ret = 0; for(int i = x;i > 0;i -= lowbits(i)){ for(int j = y;j > 0;j -= lowbits(j)){ ret += C[i][j]; } } return ret; } int main(){ //freopen("D://imput.txt","r",stdin); scanf("%d", &X); while(X --){ memset(C, 0, sizeof(C)); scanf("%d%d", &N, &M); while(M --){ scanf("%s", op); if(op[0] == ‘C‘){ scanf("%d%d%d%d", &x1, &y1, &x2, &y2); x2 ++; y2 ++; add(x1, y1); add(x1, y2); add(x2, y1); add(x2, y2); } else{ scanf("%d%d", &x, &y); printf("%d\n", query(x,y) & 1);//求和即代表求点 } } if(X)printf("\n"); } return 0; } 线段树代码: /* Author: 2486 Memory: 63688 KB Time: 1579 MS Language: G++ Result: Accepted */ #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r #define root 1, 1, N const int MAXN = 1000 + 5; int N, T, CASE, x1, y1, x2, y2, ret, x, y; char op[5]; int sum[MAXN << 2][MAXN << 2]; void update_r(int cr, int y1, int y2, int rt, int l, int r) { if(y1 <= l && r <= y2) { sum[cr][rt] = !sum[cr][rt]; return ; } int mid = (l + r) >> 1; if(y1 <= mid) update_r(cr, y1, y2, lson); if(y2 > mid) update_r(cr, y1, y2, rson); } void update_c(int x1, int y1, int x2, int y2, int rt, int l, int r) { if(x1 <= l && r <= x2) { update_r(rt, y1, y2, root); return; } int mid = (l + r) >> 1; if(x1 <= mid) update_c(x1, y1, x2, y2, lson); if(x2 > mid) update_c(x1, y1, x2, y2, rson); } void query_r(int cr, int y1, int y2, int rt, int l, int r) { if(sum[cr][rt]) ret ++; if(y1 <= l && r <= y2) { return ; } int mid = (l + r) >> 1; if(y1 <= mid) query_r(cr, y1, y2, lson); if(y2 > mid) query_r(cr, y1, y2, rson); } void query_c(int x1, int y1, int x2, int y2, int rt, int l, int r) { query_r(rt, y1, y2, root);//选择覆盖了子树的个数 if(x1 <= l && r <= x2) { return; } int mid = (l + r) >> 1; if(x1 <= mid) query_c(x1, y1, x2, y2, lson); if(x2 > mid) query_c(x1, y1, x2, y2, rson); } int main() { //freopen("D://imput.txt","r",stdin); scanf("%d", &CASE); while(CASE --) { memset(sum, 0, sizeof(sum)); scanf("%d%d", &N, &T); while(T --) { scanf("%s", op); if(op[0] == ‘C‘) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); update_c(x1, y1, x2, y2, root); } else { scanf("%d%d", &x, &y); ret = 0; query_c(x, y, x, y, root); printf("%d\n", ret & 1); } } if(CASE)printf("\n"); } return 0; } |
POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)
时间: 2024-12-26 15:56:44
POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)的相关文章
二维树状数组(水题) POJ1195
前段时间遇到线段树过不了,树状数组却过了的题.(其实线段树过得了的) 回忆了下树状数组. 主要原理,还是二进制位数,每一项的和表示其为它的前((最后一位1及其后)的二进制数)和,可从二进制图来看.(用线段树想一想其实只是线段树编号不同而已,本质类似) 写了下二维树状数组,几乎和一维相同,也没必要不同. #include <cstdio> #include <cstring> int l,r,x,y,n,a,p,sum[1125][1125]; inline int lowbit(i
树状数组与线段树
一:树状数组 树状数组是对一个数组改变某个元素和求和比较实用的数据结构.两中操作都是O(logn). 需求:有时候我们需要频繁地求数组的前k项和或者求数组从小标i到j的和,这样每次最坏情况下的时间复杂度就会为O(N),这样效率太低了.而树状数组主要就是为了解决这样一个问题.树状数组在求和及修改都可以在O(lgN)时间内完成. 树状数组需要额外维护一个数组,我们设为C[N],原数组为A[N], 其中每个元素C[i]表示A[i-2^k+1]到A[i]的和,这里k是i在二进制时末尾0的个数.注意通过位
HDU 1166 敌兵布阵 (线段树 &; 树状数组)
敌兵布阵 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u SubmitStatus 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的
Lightoj 1112 - Curious Robin Hood 【单点改动 + 单点、 区间查询】【树状数组 水题】
1112 - Curious Robin Hood PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick.
算法基础-树状数组
今天我们分享一下树状数组,前置知识-了解树的结构,知道什么是左右儿子,各个节点的名称,也就是有点基础吧.今天以一个实际问题引出树状数组吧,中查询l-r的区间.(以B站大佬的课件为例子,可以关注下,在最后放上链接) 如果是暴力的话,显然时间复杂度是接受不了的(o(n方)),为了解决这个问题,我们就要用一些高级的数据结构.就是我们今天介绍的树状数组. 首先看下树状数组是什么, 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log
hdu 1166:敌兵布阵(树状数组,练习题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 37773 Accepted Submission(s): 15923 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就
Bestcoder7(1004)hdu4988(经典问题:树状数组套treap求解动态逆序对)
Little Pony and Boast Busters Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 83 Accepted Submission(s): 32 Problem Description "I hereby challenge you, Ponyvillians: anything you can do
【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: -------------------------------------------------------------------------------- [ 3 ] 上面都不是重点--重点是树状数组的区间修改+区间查询 这个很好玩 其实也挺简单 首先依旧是引入delta数组 delta[i]表示区间 [i, n] 的共同增量 于是修改区间 [l, r] 时修改 delt
树状数组入门 hdu1541 Stars
树状数组 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询). 树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决.相比较而言,树状数组效率要
POJ-1195 Mobile phones---裸的二维树状数组(注意下标从1,1开始)
题目链接: https://vjudge.net/problem/POJ-1195 题目大意: 直接维护二维树状数组 注意横纵坐标全部需要加1,因为树状数组从(1,1)开始 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<string> 6 #include<cmath> 7 #include<