题目链接:点击打开链接
题目大意:
给你一个二维表格,执行两种操作,第一种给你左上角和右下角的坐标,让你把这个矩形内的数翻转,即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
#include
#include
#include
#include
#include
#include
#include
#include
线段树部分:
线段树要用二维线段树,也是我第一次写的二维线段树。刚开始是真的不知道怎么写。反正瞎写了一种四分树,反正不知道哪错了疯狂RE,而且后来去网上查了一下。
二维线段树貌似有两种,一种就是刚刚说的四分树,但是四分树某些情况下时间复杂度极高。而且我疯狂RE也不知道为啥。后来学习了另外一种树套树的做法。也就是x对应的每个节点也有一颗线段树,刚开始也一直在想维护的问题,后来上网看了别人的博客才发现不用这么搞,而且更新和查询的方法比较奇妙。
更新的话就是先找到符合要求的x的对应区间,其次更新对应的y线段树。但是这样会在查询的时候造成一个问题,例如,第一次更新 1,1 10,10 。那么假设当前区间恰好为1到10,就会更新当前节点的y线段树。但是如果下一次更新1,1 5,5 更新的就是上个节点的子节点的y线段树,y线段树同样也有这样的问题, 所以查询的时候就要注意,不能随意递归下去,那么如果想解决这样的问题的话就在每一次的的x节点处查询y线段树即可,y线段树也是每个节点的值都加上。这样的话就保证了你查询的值没有遗漏,
买买买
总体来说可能是这道题目偏简单,实现起来不算太麻烦,但是耗时比树状数组多好多,而且之前写线段树习惯用结构体写,换成这种线段树突然不会用结构体写了,最后忘初始化wa了好多发,可能是我代码太丑的原因。。。
#include
#include
#include
#include
#include
#include
#include
#include
#include