模拟,区间覆盖,区间合并

hdoj 1199 Color the Ball

题目的思路就是用黑的段去更新白的段,然后合并白的段。更新时,如果全被黑的覆盖了,则令白段的左位置为0。

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

struct Node {
	int l, r;
}ns[40005];
int len, n;


bool cmp( Node nd1, Node nd2 ) {
	return nd1.l < nd2.l;
}


void black( int a, int b ) {
	int i;
	for( i=0; i<len; ++i ) {
		if( ns[i].l == 0 ) continue;                                             //更新时有4中情况
		if( a > ns[i].l && a <= ns[i].r && b >= ns[i].r ) ns[i].r = a - 1;       //1.只对右端点更新
		else if( a <= ns[i].l && b >= ns[i].l && b < ns[i].r ) ns[i].l = b + 1;  //2.只对左端点更新
		else if( a > ns[i].l && b < ns[i].r ) {                                  //3.同时对左右端点更新
			ns[len].l = b + 1;
			ns[len].r = ns[i].r;
			ns[i].r = a - 1;
			len ++;
		} else if( a <= ns[i].l && b >= ns[i].r ) {                              //4.黑的把白的全部覆盖
			ns[i].l = 0;
		}
	}
}


void white() {
	int i;
	sort( ns, ns+len, cmp );
	for( i=1; i<len; ++i ) {
		if( ns[i-1].l == 0 ) continue;
		if( ns[i-1].r + 1 >= ns[i].l ) {                                         //排序后合并时2种情况
			ns[i].l = ns[i-1].l;												 //1.可以拓展第i段的左端点
			if( ns[i-1].r > ns[i].r ) ns[i].r = ns[i-1].r;                       //2.可以拓展第i段的右端点
		}
	}
}



int main() {
//	freopen( "c:/aaa.txt", "r", stdin );
	char c;
	int a, b, maxx, p, i;
	while( scanf( "%d", &n ) == 1 ) {
		len = 0;
		while( n-- ) {
			scanf( "%d %d %c", &a, &b, &c );
			if( a > b ) swap( a, b );
			if( c == 'w' ) {
				ns[len].l = a;
				ns[len].r = b;
				len ++;
			} else black( a, b );
		}
		white();
		maxx = 0;
		p = 0;
		for( i=0; i<len; ++i ) {
			if( ns[i].l == 0 ) continue;
			if( ns[i].r - ns[i].l + 1 > maxx ) {
				maxx = ns[i].r - ns[i].l + 1;
				p = i;
			}
		}
		printf( "%d %d\n", ns[p].l, ns[p].r );
	}
	return 0;
}

posted on 2011-03-21 21:34  CrazyAC  阅读(297)  评论(0编辑  收藏  举报