题目描述
在山的那边海的那边,有一群蓝精灵,他们活泼又聪明,他们……偶然有一天发现了一组神奇的逻辑表达式,这组表达式可以表示数字x处于的范围。
例如
x >= 3 && x <= 5 ||
x >= 8 && x <= 11 ||
x >= 7 ||
x <= 0
可是蓝精灵们觉得这样的表达式过于冗杂了,他们立志要不破坏x表达范围的同时将表达式简化,使这组表达式出现的与x比较的整数常量尽可能少。
蓝精灵们发现了一个秘密,x一定是[-32768,32767]内的数字。
输入
输入包含T行。
每一行有一个或两个比较表达式组成,由运算符"&&“分隔,每个比较都是以"x"开头,后面是操作符”>=“或”<=",再后面是一个整型常量。当一行中包含两个比较时,第一个总是">="。
除了最后一行之外,所有行都由运算符"||“结尾。一行中的每个符号都由一个空格隔开(”>=“是一个符号,”<="同理),行首和行尾没有多余的空格。
输出要求
输出包含若干行,格式与输入格式相同,按照表达式中数字的大小从小到大输出。对所有整数x产生与输入表达式相同的比较结果,在其文本中包含尽可能少的行数。
注意,题目默认x>=-32768 && x<=32767。特别地,如果表达式对[-32768,32767]内所有整数都为真,则写一行单词"true"。如果表达式对[-32768,32767]内所有整数都为假,则写一行单词"false"。
如果某个区间内只包含一个常数c,则输出"x >= c && x <=c"。
样例1
样例输入:
x >= 3 && x <= 5 ||
x >= 8 && x <= 11 ||
x >= 7 ||
x <= 0
样例输出:
x <= 0 ||
x >= 3 && x <= 5 ||
x >= 7
样例2
样例输入:
x >= 5 && x <= 3
样例输出:
false
样例3
样例输入:
x <= 5 ||
x >= -3
样例输出:
true
样例4
样例输入:
x >= -32768 && x <= 0 ||
x <= 0
样例输出:
x <= 0
数据范围
对于30%的数据,1<=T<=100
对于100%的数据,1<=T<=1000,所有数据绝对值<=100000
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstring>
#include <queue>
#define MIN -32768
#define MAX 32767
using std::set;
using std::pair;
using std::make_pair;
using std::queue;
set<pair<int, int> > area;
typedef pair<int, int> pr;
void orLimit(int left, int right)
{
// printf("s+ [%d, %d]", left, right);
queue<pr> q;
for (set<pr>::iterator it = area.begin(); it != area.end(); it++)
{
if (it->second < left - 1) continue;
if (it->first > right + 1) break;
left = std::min(it->first, left);
right = std::max(it->second, right);
// area.erase(it);
q.push(make_pair(it->first, it->second));
}
while (!q.empty())
{
area.erase(area.find(q.front()));
q.pop();
}
area.insert(make_pair(left, right));
// printf(" +s\n");
}
void read(char *s)
{
std::cin.getline(s, 1800);
}
int main()
{
while(true)
{
char in[1800];
int num;
int l = -1, r = -1;
int g;
char x[3], op1[3], mid[3], xx[2], op2[3], end[3];
bool exit = false;
read(in);
g = sscanf(in, "%s %s %d %s %s %s %d %s", x, op1, &l, mid, xx, op2, &r, end);
if (g < 1)
{
area.insert(make_pair(MIN, MAX));
break;
}
if (g <= 4)
{
exit = g != 4;
if (op1[0] == '<')
{
r = l;
l = MIN;
}
else
{
r = MAX;
}
}
else
{
exit = g != 8;
}
if (l <= r)
orLimit(l, r);
if (exit) break;
}
if(area.size() == 0)
{
printf("false\n");
}
else
{
int aaa = 0;
for (set<pr>::iterator it = area.begin(); it != area.end(); it++)
{
if (it->first <= MIN && it->second >= MAX)
{
printf("true");
}
else if (it->first <= MIN)
{
printf("x <= %d", it->second);
}
else if (it->second >= MAX)
{
printf("x >= %d", it->first);
}
else
{
printf("x >= %d && x <= %d", it->first, it->second);
}
if (aaa != area.size() - 1)
{
printf(" ||\n");
}
else
{
printf("\n");
}
aaa++;
}
}
return 0;
}
逻辑表达式
将输入的各个表达式按照分隔符分割;结构体储存各个左右端点
按照左区间排序,不断合并相交的区间;不相交则从下一个区间开始。
最后所有交集输出即可
模测之后助教有讲解过代码