POJ 2155 二维线段树【线段树套线段树】

博客介绍了POJ 2155题目的解题思路,该问题涉及二维区间内的矩形操作,其中01矩阵中的元素需要翻转。通过使用线段树套线段树的方法来解决,每个节点都是一个一维线段树。由于POJ平台对C++的限制,需要注释部分头文件。博客提到此二维线段树可能不支持动态更新,但本题可以不使用标记操作。

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

题目大意:


二维区间里,某个矩形里都是01, 选一个矩形,里面数字01翻转。


最后不停的问某个坐标是0还是1.


POJ不支持C++!1所以常用头文件要注释掉很多……



大致二维线段树就是这样的了……



每个节点都是一个线段树。


QC大爷说二维线段树不支持打标记。好像这题也不用打标记了,只能标记永久化



//#include <bits/stdc++.h>
//#include <ext/pb_ds/priority_queue.hpp>
//#include <tr1/unordered_map>
//#include <ctime>
//using std::tr1::unordered_map;
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cstdio>

using std::sort;
//using std::bitset;
using std::max;
using std::cout;
//using std::stack;
using std::cin;
using std::endl;
using std::swap;
//using std::pair;
//using std::vector;
//using std::set;
//using std::map;
//using std::multiset;
//using std::queue;
using std::greater;
using std::string;
//using std::priority_queue;
//using std::max_element;
//using std::min_element;

//using __gnu_pbds::pairing_heap_tag;
//__gnu_pbds::priority_queue<int, greater<int>, pairing_heap_tag> heap;
#define Hash unordered_map
#define pr(x) cout<<#x<<" = "<<x<<" "
#define prln(x)    cout<<#x<<" = "<<x<<endl


#define lson o*2, L, M
#define rson o*2+1, M + 1,R

int cov[4001][4001];
int n, m;
int xql, xqr, yql, yqr;

void init()
{
	scanf("%d%d", &n, &m);
	memset(cov, 0, sizeof(cov));
}

void y_update(int k, int o, int L, int R)
{
	if (yql <= L && R <= yqr)
	{
		cov[k][o] ^= 1;
		return;
	}
	int M = L + (R-L)/2;
	if (yql <= M)	y_update(k, lson);
	if (yqr > M)	y_update(k, rson);
}

void x_update(int o, int L, int R)
{
	//cout<<o<<" "<<L<<" "<<R<<" "<<xql<<" "<<xqr<<endl;
	if (xql <= L && R <=xqr)
	{
		y_update(o, 1, 1, n);
		return;
	}
	int M = L + (R - L)/2;
	if (xql <= M)	x_update(lson);
	if (xqr > M)	x_update(rson);
}

int ans;
int qx, qy;


void y_query(int k, int o, int L, int R)
{
	ans ^= cov[k][o];
//	if (qy <= L && R <= qy)
	if (L ==R)
	{
		return;
	}
	int M = L + (R - L)/2;
	if (qy <= M)	y_query(k, lson);
	else y_query(k, rson);
}

void x_query(int o, int L, int R)
{
	y_query(o, 1, 1, n);
	//if (qx <= L && R<=qx)
	if (L==R)
	{
		return;	
	}
	int M = L + (R - L)/2;
	if (qx <= M)	x_query(lson);
	else x_query(rson);
}

void doit()
{
	while (m--)
	{
		char flag;
		//prln(flag);
		getchar();
		scanf("%c", &flag);
		//prln(flag);
		if (flag=='C')
		{
			scanf("%d%d%d%d", &xql, &yql, &xqr, &yqr);
			//cout<<xql<<" "<<xqr<<" "<<yql<<" "<<yqr<<endl;
			x_update(1, 1, n);
			//cout<<flag<<" "<<xql<<" "<<xqr<<" "<<yql<<" "<<yqr<<endl;
		}
		else
		{
			scanf("%d%d", &qx, &qy);
			ans = 0;
			x_query(1, 1, n);
			printf("%d\n", ans);
			//cout<<flag<<" "<<qx<<" "<<qy<<endl;
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	int sb=0;
	while (T--)
	{
		if (sb)	printf("\n");
		++sb;
		init();	
		doit();
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值