POJ 3225 Help with Intervals 线段树

 题意:给出一个区间 0 - 65535。五种操作:

OperationNotation

Definition

UnionAB{x : xA or xB}
IntersectionAB{x : xA and xB}
Relative complementationAB{x : xA but x B}
Symmetric differenceAB(AB) ∪ (BA)
经过一系列操作后,输出最后集合的区间。

题解:说到底只有三种操作,将某区间全部置0,全部置1,全部取反。开区间与闭区间要注意区分,采用全部乘2的方式,是奇数则表明是‘(’,或者‘)’。偶数则是‘[',或者’]'。具体看代码。
#include<cstring>
#include<iostream>
using namespace std;

#define N 65535*2
#define L(u) (u<<1)
#define R(u) (u<<1|1)
int cnt;

struct RANGE
{
	int l, r;
} ran[N+10];

struct NODE
{
	int l, r, mid, v, change;
	void operChange ()
	{
		/* 注意下面三个量的更新顺序, 当v!=-1时,保证change=0 */
		if ( change ) change = 0; // 若原来记录需要改变,现在变成不要改变
		else if ( v != -1 ) v ^= 1; // 若原来节点是纯色,且不要改变,现在将节点颜色取反
		else change = 1; // 若原来不要改变,且不是纯色,则记录要改变
	}
} node[4*N];

inline void updateDown ( int u )
{
	if ( node[u].v != -1 )
	{
		node[L(u)].v = node[R(u)].v = node[u].v;
		node[L(u)].change = node[R(u)].change = node[u].change = 0;
		//node[u].v = -1;  /* node[u]的子节点全部与node[u]的值相等,可以不向下跟新 */
	}

	if ( node[u].change )
	{
		node[L(u)].operChange ();
		node[R(u)].operChange ();
		node[u].change = 0;
	}
}

inline void updateUp ( int u ) /* 注意向上更新的性质,若node[u].v!=-1,那么它的所有子节点的值都与node[u].v相等 */
{
	if ( node[L(u)].v == node[R(u)].v ) 
		node[u].v = node[L(u)].v; 
	else node[u].v = -1;
}


void build ( int u, int l, int r )
{
	node[u].l = l;
	node[u].r = r;
	node[u].v = 0;
	node[u].change = 0;
	if ( l == r ) return;
	node[u].mid = ( l + r ) >> 1;
	build ( L(u), l, node[u].mid );
	build ( R(u), node[u].mid+1, r );
}

void cover ( int u, int l, int r )
{
	if ( l > node[u].r || r < node[u].l ) return;
	if ( node[u].v == 1 ) return; // 节点已经为1,那么它的子节点一定为1

	if ( node[u].l == l && node[u].r == r )
	{
		node[u].v = 1;
		node[u].change = 0;
		return;
	}

	updateDown(u);
	if( r <= node[u].mid )
		cover ( L(u), l, r );
	else if ( l > node[u].mid )
		cover ( R(u), l, r );
	else
	{
		cover ( L(u), l, node[u].mid );
		cover ( R(u), node[u].mid+1, r );
	}
	updateUp ( u );
}

void del ( int u, int l, int r )
{
	if ( l > node[u].r || r < node[u].l ) return;
	if ( node[u].v == 0 ) return; //节点已经为0,那么它的子节点一定为0

	if ( node[u].l == l && node[u].r == r )
	{
		node[u].v = 0;
		node[u].change = 0;
		return;
	}

	updateDown(u);
	if( r <= node[u].mid )
		del ( L(u), l, r );
	else if( l > node[u].mid )
		del ( R(u), l, r );
	else
	{
		del ( L(u), l, node[u].mid );
		del ( R(u), node[u].mid+1, r );
	}
	updateUp ( u );
}

void negate ( int u, int l, int r )
{
	if ( l > node[u].r || r < node[u].l ) return;

	if ( node[u].l == l && node[u].r == r )
	{
		if ( node[u].v != -1 )
			node[u].v ^= 1;
		else node[u].change ^= 1;
		return;
	}

	updateDown(u);
	if ( r <= node[u].mid )
		negate ( L(u), l, r );
	else if ( l > node[u].mid )
		negate ( R(u), l, r );
	else
	{
		negate ( L(u), l, node[u].mid );
		negate ( R(u), node[u].mid+1, r );
	}
	updateUp ( u );
}

void query ( int u )
{
	if ( node[u].v == 1 )
	{
		cnt++;
		ran[cnt].l = node[u].l;
		ran[cnt].r = node[u].r;
		return;
	}
	if ( node[u].v == 0 ) return;
	if ( node[u].l == node[u].r ) return;

	updateDown(u);
	query ( L(u) );
	query ( R(u) );
}

int main()
{

	int l, r;
	char oper, lch, rch;

	build( 1, 0, N );

	while ( scanf ("%c %c%d,%d%c%*c",&oper,&lch,&l,&r,&rch) != EOF )
	{
		l *= 2;  if ( lch == '(' ) l++;
		r *= 2;  if ( rch == ')' ) r--;
	  
		switch ( oper )
		{
			case 'U':
				cover ( 1, l, r ); break;  // 并集

			case 'I': 
				if ( l > 0 )
				    del ( 1, 0, l-1 );      // 交集
				if ( r < N )
				    del ( 1, r+1, N ); break;

			case 'D': 
				del ( 1, l, r ); break;  // S - T

			case 'C':
				if ( l > 0 )
				    del ( 1, 0, l-1 );    // T - S
				if ( r < N )
				    del ( 1, r+1, N );
				negate ( 1, l, r ); break;

			case 'S':                           // 对称差集
				negate ( 1, l, r ); break;

			default: break;;
		}
	}

	cnt = 0;
	query ( 1 );
	if ( cnt == 0 )
	{
		printf("empty set\n");
		return 0;
	}

    int s, e;
	for ( int i = 1; i <= cnt; i++ )
	{	
		s = -1;
		if ( s == -1 ) s = ran[i].l;
		while ( i <= cnt && ran[i].r == ran[i+1].l-1 ) i++;
		if ( i > cnt ) i = cnt;
		e = ran[i].r;

		if ( s % 2 == 0 )
			printf ( "[%d,", s / 2 );
		else
			printf ( "(%d,", s / 2 );
	
		if ( e % 2 == 0 )
			printf ( "%d] ", e / 2 );
		else 
			printf ( "%d) ", (e+1) / 2 );
	} 
	putchar('\n');		
	return 0;
}

写的精简一些如下,但是效率不如上面的

#include<cstring>
#include<iostream>
using namespace std;

#define N 65535*2
#define L(u) (u<<1)
#define R(u) (u<<1|1)
int array[N+3];

struct NODE
{
    int l, r;
    int cover;
    int change;
    void fun()
    {
        if ( change ) change = 0;
        else if ( cover != -1 ) cover^=1;
        else change=1;
    }
} node[N*4];

void build ( int u, int l, int r )
{
    node[u].l = l;
	node[u].r = r;
    node[u].cover=0;
    node[u].change=0;
    if ( l == r ) return;
    int mid = ( l + r ) >> 1;
    build ( L(u), l, mid );
    build ( R(u), mid+1, r );
}

inline void updateDown ( int u )
{
	if ( node[u].cover != -1 )
    {
        node[L(u)].cover = node[R(u)].cover = node[u].cover;
        node[L(u)].change = node[R(u)].change = node[u].change = 0;
        node[u].cover = -1;
    }
    if ( node[u].change )
    {
        node[L(u)].fun();
        node[R(u)].fun();
        node[u].change=0;
    }
}

inline void updateUp ( int u )
{
	if ( node[L(u)].cover == node[R(u)].cover )
        node[u].cover = node[L(u)].cover;
    else node[u].cover = -1;
}


void cover ( int u, int l, int r, int v )
{
    if ( l > node[u].r || r < node[u].l )
		return;
    if ( l <= node[u].l && node[u].r <= r )
    {
        node[u].cover = v;
        node[u].change = 0;
        return;
    }
	updateDown ( u );
    int mid = ( node[u].l + node[u].r ) >> 1;
    if ( r <= mid )
        cover ( L(u), l, r, v );
    else if ( l > mid )
        cover ( R(u), l, r, v );
    else
    {
        cover ( L(u), l, mid, v );
        cover ( R(u), mid+1, r, v );
    }
	updateUp ( u );
}

void negate ( int u, int l, int r )
{
    if ( l > node[u].r || r < node[u].l )
		return;
    if ( l <= node[u].l && node[u].r <= r )
    {
        if ( node[u].cover != -1)
        {
            node[u].cover ^= 1;
			return;
        }
        node[u].change ^= 1;
		return;
    }
	
    updateDown ( u );
    int mid = ( node[u].l + node[u].r ) >> 1;
    if ( r <= mid )
        negate ( L(u), l, r );
    else if ( l > mid )
        negate ( R(u), l, r );
    else 
    {
        negate ( L(u), l, r );
        negate ( R(u), l, r );
    }
    updateUp ( u );
}


void query ( int u )
{
    if ( node[u].l == node[u].r )
    {
        array[node[u].l] = node[u].cover;
        return;
    }
    updateDown ( u );
    query ( L(u) );
    query ( R(u) );
}

int main()
{
    int l, r;
	char oper, lch, rch;
    build ( 1, 0, N );
	memset ( array, 0, sizeof(array) );

    while(scanf("%c %c%d,%d%c%*c",&oper,&lch,&l,&r,&rch) != EOF )
    {
        l *= 2;
		r *= 2;
        if ( lch =='(' ) l++;
        if ( rch ==')' ) r--;
        switch ( oper )
		{
		case 'U': 
			cover ( 1, l, r, 1 );
			break;

        case 'I':
            if ( l > 0 ) 
				cover ( 1, 1, l-1, 0 );
            if ( r < N )
				cover ( 1, r+1, N, 0 );
			break;

        case 'D':
            cover ( 1, l, r, 0 );
			break;

        case 'C':
			if ( l > 0 )
				cover ( 1, 0, l-1, 0);
			if ( r < N )
				cover ( 1, r+1, N, 0 );
			negate ( 1, l, r );
			break;

		case 'S':
			negate ( 1, l, r );
			break;

		default: break;;
		}
	}

	query ( 1 );
	int s, e, Empty = 1;

	for ( int i = 0; i <= N; i++ )
	{
		while ( i <= N  && !array[i] ) i++;
		s = i;
		if ( i > N ) break;

		while ( i <= N && array[i] ) i++;
		e = i-1;
		
		Empty = 0;

		if ( s % 2 == 0 )
			printf ( "[%d,", s / 2 );
		else
			printf ( "(%d,", s / 2 );
	
		if ( e % 2 == 0 )
			printf ( "%d] ", e / 2 );
		else 
			printf ( "%d) ", (e+1) / 2 );
	}

	if ( Empty )
		printf("empty set");
	putchar('\n');
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值