POJ2155-Matrix

本文介绍了一道编程题目,通过使用二维树状数组和二维线段树来解决矩阵操作的问题。具体包括如何实现矩阵元素的翻转及查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Matrix
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 28406 Accepted: 10366

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 it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions. 

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 y2", which has been described above. 

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

Source

POJ Monthly,Lou Tiancheng


题意:给你一个n*n的矩阵,一开始矩阵全为0,有两种操作,第一种是给定左上角和右下角的下标,把这个子矩形里面的0/1进行互换,第二种是询问某个点的值

解题思路:二维树状数组或者二维线段树即可,二维线段树时,因为是异或和,所以要把当前点到跟的路径上的标记累加,就是标记不下放,统计时计算所有覆盖该点的标记


二维树状数组:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <bitset>
#include <set>
#include <vector>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;

int sum[1005][1005],n, m;

int lowbit(int x)
{
	return x&-x;
}

int getsum(int x, int y)
{
	int ans= 0;
	for (int i = x; i >0; i -= lowbit(i))
		for (int j = y; j >0; j -= lowbit(j))
			ans += sum[i][j];
	return ans;
}

void add(int x, int y)
{
	for (int i = x; i <= n; i += lowbit(i))
		for (int j = y; j <= n; j += lowbit(j))
			sum[i][j]++;
}

int main()
{
	int t;
	int x1, x2, y1, y2;
	scanf("%d", &t);
	while (t--)
	{
		memset(sum, 0, sizeof sum);
		scanf("%d%d", &n, &m);
		while (m--)
		{
			char ch[5];
			scanf("%s", ch);
			if (ch[0] == 'C')
			{
				scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
				add(x2+1, y2+1);
				add(x1, y1);
				add(x2+1, y1);
				add(x1, y2+1);
			}
			else
			{
				scanf("%d%d", &x1, &y1);
				printf("%d\n", getsum(x1, y1)%2);
			}
		}
		printf("\n");
	}
	return 0;
}



二维线段树:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cctype>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;

int n, m, ans;
int x1, y1, x2, y2;
char ch[20];
struct node
{
	int y[4000];
}x[4000];

void build(int k, int kk, int l, int r)
{
	x[k].y[kk] = 0;
	if (l == r)  return;
	int mid = (l + r) / 2;
	build(k, kk << 1, l, mid);
	build(k, kk << 1 | 1, mid + 1, r);
}

void build(int k, int l, int r)
{
	build(k, 1, 1, n);
	if (l == r)  return;
	int mid = (l + r) / 2;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
}

void update(int k, int kk, int l, int r, int ll, int rr)
{
	if (l >= ll&&r <= rr)
	{
		x[k].y[kk] ^= 1;
		return;
	}
	int mid = (l + r) / 2;
	if (ll <= mid) update(k, kk << 1, l, mid, ll, rr);
	if (rr > mid)  update(k, kk << 1 | 1, mid + 1, r, ll, rr);
}

void update(int k, int l, int r, int ll, int rr, int y1, int y2)
{
	if (l >= ll&&r <= rr)
	{
		update(k, 1, 1, n, y1, y2);
		return;
	}
	int mid = (l + r) / 2;
	if (ll <= mid)  update(k << 1, l, mid, ll, rr, y1, y2);
	if (rr > mid)  update(k << 1 | 1, mid + 1, r, ll, rr, y1, y2);
}

void query1(int k, int kk, int l, int r, int y)
{
	ans ^= x[k].y[kk];
	if (l == r)  return;
	int mid = (l + r) / 2;
	if (y <= mid) query1(k, kk << 1, l, mid, y);
	else query1(k, kk << 1 | 1, mid + 1, r, y);
}

void query(int k, int l, int r, int x, int y)
{
	query1(k, 1, 1, n, y);
	if (l == r) return;
	int mid = (l + r) / 2;
	if (x <= mid) query(k << 1, l, mid, x, y);
	else query(k << 1 | 1, mid + 1, r, x, y);
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &m);
		build(1, 1, n);
		for (int i = 1; i <= m; i++)
		{
			scanf("%s", ch);
			if (ch[0] == 'C')
			{
				scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
				update(1, 1, n, x1, x2, y1, y2);
			}
			else
			{
				scanf("%d%d", &x1, &y2);
				ans = 0;
				query(1, 1, n, x1, y2);
				printf("%d\n", ans);
			}
		}
		printf("\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值