模拟,区间覆盖,区间合并
题目的思路就是用黑的段去更新白的段,然后合并白的段。更新时,如果全被黑的覆盖了,则令白段的左位置为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; }