您的位置:首页 > 其它

poj 3225 Help with Intervals(过题啦啦~)

2011-09-27 14:07 375 查看
这个题是线段树经典题目,相信学过线段树的童鞋一定见过。。

我之前一直木有做,没仔细看,觉得应该不算太难,但是懒得做。。

前天一ACMer跟我聊线段树,谈到一种情况,就是线段和点同时有意义的时候,我当时就想,那扩大二倍应该就没啥问题了,然后他就说到这个题了。。。然后我决定做一下~

sha崽大牛线段树上面有这个题,可以把并交差与区间覆盖异或联系起来,引用下。具体地:

如果以1代表当前有值的话,那么假设T的区间为l,r,开闭先不管。。

U:把区间[l,r]覆盖成1

I:把[-∞,l)(r,∞]覆盖成0

D:把区间[l,r]覆盖成0

C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换

S:[l,r]区间0/1互换

注意区间开闭的判断。

最后找连续的区间即可。

具体的我的代码有注释。。。难得我写一次注释。。嘿嘿。。代码很长。。。我觉得我缩不了了。。。><。。。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

using namespace std;

const int MAX = 70000*2;
bool a[MAX<<2];
struct Tnode{				// 一维线段树 
    int l,r,cover;
    bool x;
    int len() { return r - l;}
    int mid() { return MID(l,r);}
    bool in(int ll,int rr) { return l >= ll && r <= rr; }
    void lr(int ll,int rr){ l = ll; r = rr;}
};
Tnode node[MAX<<2];
void Build(int t,int l,int r)
{
	node[t].x = false;				//	x 为 false 代表不异或 
	node[t].cover = 0;				//  cover为-1代表当前区间有0有1, 初始化为空集合 
	node[t].lr(l,r);
	if( node[t].len() == 1 ) return ;
	int mid = MID(l,r);
	Build(L(t),l,mid);
	Build(R(t),mid,r);
}

void Updata_x(int t)					// 向下更新异或,因为cover在上一条命令结束时已经更新过了 
{										// 保证异或标记为真,那么cover必然等于-1 
	if( node[t].len() == 1 )
	{
		if( node[t].x )
		{
			node[t].x = false;
			node[t].cover = node[t].cover ^ 1;
		}
		return ;
	}
	if( node[t].cover != -1 )
	{
		node[L(t)].cover = node[R(t)].cover = node[t].cover;
		node[L(t)].x = node[R(t)].x = false;
	}
	else
	{
		if( node[t].x )
		{
			node[L(t)].x = !node[L(t)].x;
			node[R(t)].x = !node[R(t)].x;
			if( node[L(t)].cover != -1 && node[L(t)].x )
			{
				node[L(t)].x = false;
				node[L(t)].cover = node[L(t)].cover ^ 1;
			}
			if( node[R(t)].cover != -1 && node[R(t)].x )
			{
				node[R(t)].x = false;
				node[R(t)].cover = node[R(t)].cover ^ 1;
			}
			node[t].x = false;
		}
	}
}

void Updata_cover(int t)			// 更新父节点cover 
{
	if( node[L(t)].cover == node[R(t)].cover )
		node[t].cover = node[L(t)].cover;
	else
		node[t].cover = -1;
}

void Updata(int t, int l, int r, int op, int val)
{
	if( l >= r || l < 0 ) return ;	//	防止出现一些非法状况 
	Updata_x(t);
	if( node[t].in(l,r) )
	{
		if( op == 0 )			// 覆盖操作,把异或标记清空 
		{
			node[t].cover = val;
			node[t].x = 0;
		}
		else
		{
			if( node[t].cover != -1 )
				node[t].cover = node[t].cover ^ 1;	// 当前区间被覆盖,更改cover的值 
			else
				node[t].x = !node[t].x;				// 当前区间 有0有1 
		}                          
		return ;
	}
	if( node[t].len() == 1 ) return ;
	int mid = node[t].mid();
	if( l < mid ) Updata(L(t), l, r, op, val);
	if( r > mid ) Updata(R(t), l, r, op, val);
	Updata_cover(t);
}

void Query(int t)
{
	Updata_x(t);
	if( node[t].len() == 1 )
	{
		 a[ node[t].l ] = ( node[t].cover ? true : false );
		 return ;
	}
	Query(L(t));
	Query(R(t));
}
	
void solve(char op, char l, char r, int x, int y)
{
	int lb, lk, rb, rk, ll, rr;
	lb = 2*x;		lk = 2*x + 1;	//左闭 左开 
	rb = 2*y + 1; 	rk = 2*y;		//右闭 右开 
	ll = ( l == '(' ? lk : lb );
	rr = ( r == ')' ? rk : rb ); 
	
	switch( op )
	{
		case 'U':
			Updata(1, ll, rr, 0, 1);
			break;
			
		case 'I':
			Updata(1, 0, ll, 0, 0);
			Updata(1, rr, MAX, 0, 0);
			break;
			
		case 'D':
			Updata(1, ll, rr, 0, 0);
			break;
			
		case 'C':
			Updata(1, ll, rr, 1, 0);
			Updata(1, 0, ll, 0, 0);
			Updata(1, rr, MAX, 0, 0);
			break;
		
		case 'S':
			Updata(1, ll, rr, 1, 0);
	}
}

void output()
{
	int cnt = 0;
	
	Query(1);
	
	FOR(i, 0, MAX*2)
	{
		if( a[i] && cnt % 2 == 0 )
		{
			if( cnt != 0 )
				printf(" ");
			printf( i % 2 == 1 ? "(%d," : "[%d,", i/2);
			cnt++;
		}
		if( !a[i] && cnt % 2 == 1 )
		{
			printf( i % 2 == 1 ? "%d]" : "%d)", i/2);
			cnt++;
		}
	}
	if( cnt == 0 )
		printf("empty set");
	printf("\n");
}
/*
左闭  2*x
左开  2*x + 1
右闭  2*y + 1
右开  2*y
*/ 
int main()
{
	char op[5], s[100], l, r;
	int x, y;
	
	memset(a, false, sizeof(a));
	Build(1, 0, MAX);
	
	while( ~scanf("%s%s", op, s) )
	{
		sscanf(s, "%c%d,%d%c", &l, &x, &y, &r);
		solve(op[0], l, r, x, y);
	}
	
	output();
	
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: