题意:
有无穷多个小球排在一列,编号为1~infinite,然后为这些小球涂色,刚开始时小球都是黑色的,每次给a~b编号的小球涂黑色或者白色,之后统计连续白色小球最长的小球开始编号和结束编号,如果存在多个,输出编号小的那个,如果不存在白色小球序列,则输出Oh, my god
解题:
每次输入,判断是白色还是黑色,如果是白色,直接加入队列,如果是黑色,则与队列中的序列进行比较,如果当前的涂黑序列能够分裂队列中的序列为多个白色,那么就将其分裂,并将分裂的结果加入队列,直到处理完毕。
处理完之后按照结束位置从小到大的顺序对该队列进行排序,之后循环合并相邻的序列为一个大的序列,直到不能再合并。最后求出最大序列。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Segment
{
public:
int startNum;
int endNum;
Segment(int startNum, int endNum):startNum(startNum), endNum(endNum){}
Segment(){}
~Segment(){}
};
bool cmp(Segment a, Segment b)
{
if (a.endNum != b.endNum)return a.endNum < b.endNum;
return a.startNum < b.startNum;
}
vector <Segment > segments;
void blackSegment(const Segment &sgmt)
{
vector<Segment >::iterator it;
int n = (int)segments.size();
for (int i = 0; i < n; ++i){
Segment tmp = segments[i];
if (tmp.startNum > sgmt.endNum || tmp.endNum < sgmt.startNum)continue;//黑不在该区间内
if (tmp.startNum >= sgmt.startNum && tmp.endNum <= sgmt.endNum){//该区间在黑内
it = segments.begin()+i;
segments.erase(it);
n--, i--;
continue;
}
if (tmp.startNum < sgmt.startNum){//该区间左侧有没被涂黑的球
segments.push_back(Segment(tmp.startNum, sgmt.startNum-1));
}
if (tmp.endNum > sgmt.endNum){//该区间右侧有没被涂黑的球
segments.push_back(Segment(sgmt.endNum+1, tmp.endNum));
}
it = segments.begin()+i;
segments.erase(it);
n--, i--;
//--------------------DebugS--------------------
//cout << "IN:size->" << segments.size() << endl;
//--------------------DebugE--------------------
}
}
//--------------------DebugS--------------------
ostream & operator<<(ostream&out, const vector<Segment > & sgmt)
{
out << "size:" << sgmt.size() << endl;
for (int i = 0; i < (int)sgmt.size(); ++i){
const Segment &tmp = sgmt[i];
out << "(" << tmp.startNum << "," << tmp.endNum << ") ";
}
return out;
}
//--------------------DebugE--------------------
//合并区间
void mergeSegment()
{
if (segments.size() <= 1)return ;
int flag = true;
while (flag){
int n = segments.size();
vector<Segment >::iterator it;
flag = false;
for (int i = 1; i < n; ++i){
if (segments[i-1].endNum+1 >= segments[i].startNum){
segments[i-1].endNum = segments[i].endNum;
if (segments[i-1].startNum > segments[i].startNum)segments[i-1].startNum = segments[i].startNum;
it = segments.begin()+i;
segments.erase(it);
n--, i--;
flag = true;
}
}
}
}
//计算结果
void getAnswer()
{
if (segments.size() == 0){
printf ("Oh, my god\n");
return ;
}
int maxWhiteIndex = 0, maxWhiteLen = segments[0].endNum-segments[0].startNum;
for (int i = 1; i < (int)segments.size(); ++i){
int len = segments[i].endNum - segments[i].startNum;
if (maxWhiteLen < len){
maxWhiteIndex = i;
maxWhiteLen = len;
}
}
printf ("%d %d\n", segments[maxWhiteIndex].startNum, segments[maxWhiteIndex].endNum);
}
int main()
{
int n, a, b;
char c;
while (scanf ("%d", &n)!=EOF){
while (!segments.empty())segments.clear();
while (n--){
scanf ("%d%d %c", &a, &b, &c);
if (a > b)swap(a, b);
if (c == 'w')segments.push_back(Segment(a, b));
else {
blackSegment(Segment(a, b));
}
//--------------------DebugS--------------------
//cout << segments << endl;
//--------------------DebugE--------------------
}
sort(segments.begin(), segments.end(), cmp);
//--------------------DebugS--------------------
//cout << "After sort: " << segments << endl;
//--------------------DebugE--------------------
mergeSegment();
//--------------------DebugS--------------------
//cout << "After merge: " << segments << endl;
//--------------------DebugE--------------------
getAnswer();
}
return 0;
}