POJ 2155 二维线段树 修改区间查询点

     这道线段树,我用的是完全暴力的方式,中间没有优化;

     说实话,简直坑爹,对于n长度的区间的线段树 ,它的节点数目为N左右,第二维开N的大小居然过不了 ,真是大哭了,检查了好久好久,本来昨天就该过的,真坑爹!!!!

方法:二维线段树 ( 树套树 ) ,修改区间查询点;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std ;

const int N = 1000 + 11 ;

struct Node {
	int lson , rson ;
	int mid() {return (lson+rson)>>1 ;}
};

Node arr[N<<2][N<<1] ;//第二维为N过不了
int dimension[N<<2] ;
bool flag[N<<2][N<<1] ;
int x1 , y1 , x2 , y2 ;
int n ;
int dim ;
int ans ;

void build(int l , int r , int site , int dimen) {
	arr[site][dimen].lson = l ; arr[site][dimen].rson = r ;
	flag[site][dimen] = false ;
	if(dimen == 0) {
		dimension[site] = dim ;
		build(1 , n , 1 , dim++) ;
	}
	if(l == r) return ;
	int mid = arr[site][dimen].mid() ;
	build(l , mid , site<<1 , dimen) ;
	build(mid+1 , r , site<<1|1 , dimen) ;
}

void update(int site , int dimen) {
	if(dimen == 0 && x1 <= arr[site][dimen].lson && arr[site][dimen].rson <= x2) {
		update(1 , dimension[site]) ;
		return ;
	}else if(dimen != 0 && y1 <= arr[site][dimen].lson && arr[site][dimen].rson <= y2) {
		flag[site][dimen] = !flag[site][dimen] ;
		return ;
	}
	if(arr[site][dimen].lson == arr[site][dimen].rson) return ;
	int mid = arr[site][dimen].mid() ;
	if(dimen == 0 && x1 <= mid || dimen != 0 && y1 <= mid) update(site<<1 , dimen) ;
	if(dimen == 0 && x2 > mid || dimen != 0 && y2 > mid) update(site<<1|1 , dimen) ;
}

void query(int site , int dimen) {
	if(dimen == 0 && arr[site][dimen].lson <= x1 && x1 <= arr[site][dimen].rson) {
		query(1 , dimension[site]) ;
	}else if(dimen != 0 && arr[site][dimen].lson <= y1 && y1 <= arr[site][dimen].rson) {
		if(flag[site][dimen]) ++ans ;
	}
	if(arr[site][dimen].lson == arr[site][dimen].rson) return ;
	int mid = arr[site][dimen].mid() ;
	if(dimen == 0 && x1 <= mid || dimen != 0 && y1 <= mid) query(site<<1 , dimen) ;
	if(dimen == 0 && x1 > mid || dimen != 0 && y1 > mid) query(site<<1|1 , dimen) ;
}

int main() {//freopen("data.in" , "r" , stdin);
    //freopen("data1.out" ,"w" , stdout) ;
	int t , m ;
	scanf("%d" ,&t) ;
	while(t--) {
		scanf("%d%d" ,&n ,&m) ;
		dim = 1 ;
		build(1 ,n , 1 , 0) ;
		char s[3] ;
		while(m--) {
			scanf("%s" ,s) ;
			if(s[0] == 'C') {
				scanf("%d%d%d%d" ,&x1 ,&y1 ,&x2 ,&y2) ;
				update(1 , 0) ;
			}else {
				scanf("%d%d" ,&x1 , &y1) ;
				ans = 0 ;
				query(1 , 0) ;
				if(ans&1) printf("1\n") ;
				else printf("0\n");
			}
		}
		if(t) printf("\n");
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值