POJ 2155 Matrix 二维树状数组

本文介绍了一种使用二维树状数组解决矩形区域元素反转问题的方法。通过定义f(x,y,c)来表示前x行中的前y列元素修改成c的操作,文章详细解释了如何通过树状数组进行区间修改与单点查询,最终实现高效处理矩形区域内元素的反转及查询。

点击打开链接

题意:n*n矩形 初始元素全部为0 有m个操作,操作1:把某个子矩形内元素反转.操作2:询问某个元素的值 n<=1e3,m<=5e4 

如果一维的n个元素 反转某个区间 可以直接用一维树状数组暴力修改 
f(x,y,c)前x行中的前y列修改成c,修改子矩形等价于操作:f(x2,y2,1)+f(x2,y1-1,-1)+f(x1-1,y2,-1)+f(x1-1,y1-1,1)
则利用二维的树状数组 更新区间 单点查询(查询这个点被多少个区间累加过) 

c[x][y] 子矩形x~x-lowbit(x)-1行的y~lowbit[y]-1]列之和 时间复杂度为O(mlog^2(n))

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=2e3+20;
int n,m;
int c[N][N];//c[x][y] 子矩形x~x-lowbit(x)-1行的y~lowbit[y]-1]列之和 
int lowbit(int x)//二进制中最后一个1 
{
	return x&(-x);
}
void update(int x,int y,int p)
{
	for(int i=x;i>=1;i-=lowbit(i))
	{
		for(int j=y;j>=1;j-=lowbit(j))
		{
			c[i][j]+=p;
		}
	}
} 
int query(int x,int y)
{
	//(x,y)被多少子矩形累加过
	int res=0; 
	for(int i=x;i<=n;i+=lowbit(i))
	{
		for(int j=y;j<=n;j+=lowbit(j))
		{
			res+=c[i][j];
		}
	}
	return res;
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(c,0,sizeof(c));
		cin>>n>>m;
		char s[2];
		int x,y,x1,y1,x2,y2;
		for(int i=0;i<m;i++)
		{
			scanf("%s",s);
			if(s[0]=='C') 
			{
				scanf("%d%d%d%d",&x1,&y1,&x2,&y2);	
				update(x2,y2,1);
				update(x1-1,y2,1);
				update(x2,y1-1,1);
				update(x1-1,y1-1,1);
			} 
			else
			{
				scanf("%d%d",&x,&y);	
				printf("%d\n",query(x,y)%2?1:0);//反转奇数次为1  		
			}	
		}
		cout<<endl; 
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值