POJ-2155:Matrix(二维线段树或二维树状数组)
来源:互联网 发布:三菱plc编程入门教程 编辑:程序博客网 时间:2024/05/29 08:26
题目链接:点击打开链接
题目大意:
给你一个二维表格,执行两种操作,第一种给你左上角和右下角的坐标,让你把这个矩形内的数翻转,即0变成1,1变成0。第二种操作就是查询某个点当前的值。
解题思路:
这道题有两种做法,分别是二维树状数组和二维线段树。以下分别讲解。
树状数组:
二维树状数组很好理解,代码也非常简单,而且最后耗时貌似也比线段树少不少。用一些简单的操作即可实现题目的要求。
假设题目让你更新 p1,q1 p2,q2 那么可以 将p1,q1,后面的点都加1,然后将不符合题目要求的区域减1,即 p2+1,q1 和 p1,q2+1 . 但是这样的话右下角一部分被重复减了两次,因此再将右下角的部分+1,即 p2+1,q2+1 后面加1. 查询的时候直接查询就可以。以下贴树状数组的代码,
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define lson rt<<1#define rson rt<<1|1using namespace std;typedef long long ll;typedef unsigned long long ULL;int n,m;char c;int d[1005][1005];void add(int i,int j,int x) //二维树状数组模板,跟一维很像{ while(i<=n) { int jj=j; while(jj<=n) { d[i][jj]+=x; jj += jj&-jj; } i += i&-i; }}int sum(int i,int j){ int s=0; while(i>0) { int jj=j; while(jj>0) { s=s+d[i][jj]; jj -= jj&-jj; } i -= i&-i; } return s;}int main(){ int QAQ; scanf("%d",&QAQ); while(QAQ--) { int p1,q1,p2,q2; scanf("%d%d",&n,&m); memset(d,0,sizeof(d)); //记得初始化 for(int i=0;i<m;i++) { scanf(" %c",&c); if(c=='C') { scanf("%d%d%d%d",&p1,&q1,&p2,&q2); //将题目要求部分加1 add(p1,q1,1); add(p1,q2+1,-1); add(p2+1,q1,-1); add(p2+1,q2+1,1); } if(c=='Q') { scanf("%d%d",&p1,&q1); printf("%d\n",sum(p1,q1)%2); //输出结果余2 } } printf("\n"); }}
线段树部分:
线段树要用二维线段树,也是我第一次写的二维线段树。刚开始是真的不知道怎么写。反正瞎写了一种四分树,反正不知道哪错了疯狂RE,而且后来去网上查了一下。
二维线段树貌似有两种,一种就是刚刚说的四分树,但是四分树某些情况下时间复杂度极高。而且我疯狂RE也不知道为啥。后来学习了另外一种树套树的做法。也就是x对应的每个节点也有一颗线段树,刚开始也一直在想维护的问题,后来上网看了别人的博客才发现不用这么搞,而且更新和查询的方法比较奇妙。
更新的话就是先找到符合要求的x的对应区间,其次更新对应的y线段树。但是这样会在查询的时候造成一个问题,例如,第一次更新 1,1 10,10 。那么假设当前区间恰好为1到10,就会更新当前节点的y线段树。但是如果下一次更新1,1 5,5 更新的就是上个节点的子节点的y线段树,y线段树同样也有这样的问题, 所以查询的时候就要注意,不能随意递归下去,那么如果想解决这样的问题的话就在每一次的的x节点处查询y线段树即可,y线段树也是每个节点的值都加上。这样的话就保证了你查询的值没有遗漏,
买买买
总体来说可能是这道题目偏简单,实现起来不算太麻烦,但是耗时比树状数组多好多,而且之前写线段树习惯用结构体写,换成这种线段树突然不会用结构体写了,最后忘初始化wa了好多发,可能是我代码太丑的原因。。。
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define xlson xl,xmid,xt<<1#define xrson xmid+1,xr,xt<<1|1#define ylson yl,ymid,xt,yt<<1#define yrson ymid+1,yr,xt,yt<<1|1using namespace std;typedef long long ll;typedef unsigned long long ULL;const int maxn=1010;int n,m,ans;int tree[maxn<<2][maxn<<2];void update_y(int q1,int q2,int yl,int yr,int xt,int yt) //更新y线段树{ if(q1<=yl&&yr<=q2) { tree[xt][yt]++; return ; } int ymid=(yl+yr)>>1; if(q1<=ymid) update_y(q1,q2,ylson); if(q2>ymid) update_y(q1,q2,yrson);}void update_x(int p1,int q1,int p2,int q2,int xl,int xr,int xt) //查找符合要求的区间{ if(p1<=xl&&xr<=p2) //找到合适的区间就更新y线段树 { update_y(q1,q2,1,n,xt,1); return ; } int xmid=(xl+xr)>>1; if(p1<=xmid) update_x(p1,q1,p2,q2,xlson); if(p2>xmid) update_x(p1,q1,p2,q2,xrson);}void query_y(int y,int yl,int yr,int xt,int yt) //查询y线段树中的值{ ans=ans+tree[xt][yt]; //将每个值都加上防止遗漏 if(yl==yr) return ; int ymid=(yl+yr)>>1; if(y<=ymid) query_y(y,ylson); if(y>ymid) query_y(y,yrson);}void query_x(int x,int y,int xl,int xr,int xt) //查询所有的x线段树{ query_y(y,1,n,xt,1); //每个x节点都查询y线段树 if(xl==xr) return ; int xmid=(xl+xr)>>1; if(x<=xmid) query_x(x,y,xlson); if(x>xmid) query_x(x,y,xrson);}int main(){ int QAQ; scanf("%d",&QAQ); while(QAQ--) { memset(tree,0,sizeof(tree)); //记得初始化 scanf("%d%d",&n,&m); char q; int p1,q1,p2,q2; for(int i=0;i<m;i++) { scanf(" %c",&q); if(q=='C') { scanf("%d%d%d%d",&p1,&q1,&p2,&q2); update_x(p1,q1,p2,q2,1,n,1); } if(q=='Q') { scanf("%d%d",&p1,&q1); ans=0; query_x(p1,q1,1,n,1); printf("%d\n",ans%2); } } printf("\n"); }}
- POJ-2155:Matrix(二维线段树或二维树状数组)
- POJ-2155-Matrix(二维树状数组 & 二维线段树)
- POJ 2155——Matrix(树套树,二维树状数组,二维线段树)
- 【线段树】 POJ 2155 Matrix 二维线段树/二维树状数组
- poj 2155 二维线段树或树状数组入门
- poj 2155 Matrix(二维树树状数组)
- poj 2155 Matrix(二维树状数组)
- POJ 2155 Matrix (二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- 【树状数组(二维)】poj 2155 Matrix
- POJ 2155 Matrix (二维树状数组)
- [poj 2155] Matrix(二维树状数组)
- POJ 2155 Matrix (二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- POJ 2155 Matrix(二维树状数组)
- Qt开发的程序发布要点
- java文件下载文件名乱码
- (转载)数据库设计中的14个技巧
- NYOJ 19 擅长排列的小明
- tkinter中可变的变量
- POJ-2155:Matrix(二维线段树或二维树状数组)
- 1022
- 剑指Offer_面试题22_栈的压入弹出序列
- 数据结构实验之串三:KMP应用
- SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation 视频语义分割demo跑通
- 欢迎使用CSDN-markdown编辑器
- 使用Webview显示html文本遇到的字符实体问题
- 框架整合____Spring整合Struts2(主流整合方式,最精简整合方式)
- FloVIZ 11.0 build 15.25.5 1CD