Codeforces Gym 101190 (NEERC 2016) H. Hard Refactoring (模擬 + 樹狀陣列)
題意
Helen had come upon a piece of code that uses a lot of “magical constants”. She found a logical expression that checks if an integer x belongs to a certain set of ranges, like the one shown below:
x >= 5 && x <= 10 ||
x >= 7 && x <= 20 ||
x <= 2 ||
x >= 21 && x <= 25 ||
x >= 8 && x <= 10 ||
x >= 100
Helen does not like “magical constants”, so she decided to refactor this expression and all similar ones in such a way, that the refactored expression still has the same Boolean result for all integers x, but it uses as few integer constants in its text as possible.
Integers in this problem, including integer x, come from the range of all signed 16 bit integers starting from
解題思路
簡單模擬,數字區間為 true
,全不取為 false
。否則按最簡表示式給出範圍。
對於輸入給的表示式,讀取其表示的區間 [l, r]
,若 l <= r
,則將其在一維數軸上 [l, r]
每個數 +1
。
對結果判斷,
對於如何快速對區間修改及單點查詢,通過樹狀陣列即可。
程式碼
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<fstream>
using namespace std;
const int BASE = 32769;
const int N = 70000;
int bin[N];
inline int lowbit(int x) { return x & -x; }
void add(int x, int w) {
for(int i=x;i<N;i+=lowbit(i))
bin[i] += w;
}
int sum(int x) {
int ret = 0;
for(int i=x;i;i-=lowbit(i))
ret += bin[i];
return ret;
}
void update(int x, int y, int w) {
add(x, w), add(y+1, -w);
}
int main()
{
freopen("hard.in", "r", stdin);
freopen("hard.out", "w", stdout);
char x[2], op[5], eop0, eop1;
int lmt, lft, rgt;
while(true)
{
lft = -32768, rgt = 32767;
scanf(" %s %s %d", x, op, &lmt);
if(op[0] == '<') rgt = lmt;
else lft = lmt;
if(cin>>eop0>>eop1) {
if(eop0 == '&') {
scanf(" %c %s %d", &x, op, &lmt);
if(op[0] == '<') rgt = min(lmt, rgt);
else lft = max(lft, lmt);
}
if(lft <= rgt)
update(lft + BASE, rgt + BASE, 1);
if(eop0 == '&') {
if(cin>>eop0>>eop1);
else break;
}
}
else {
if(lft <= rgt)
update(lft + BASE, rgt + BASE, 1);
break;
}
}
int cnt = 0;
lft = -BASE;
bool flg = false;
for(int i=1, val;i<=BASE + 32767;i++)
{
val = sum(i);
cnt += (val > 0 ? 1 : 0);
if(lft == -BASE && val)
lft = i-BASE;
if(lft != -BASE && val == 0) {
if(flg) printf(" ||\n");
if(lft == 1-BASE)
printf("x <= %d", i-BASE-1);
else
printf("x >= %d && x <= %d", lft, i-BASE-1);
lft = -BASE;
flg = true;
}
}
if(cnt == 0)
printf("false\n");
else if(cnt == 32768*2)
printf("true\n");
else if(lft != -BASE) {
if(flg) printf(" ||\n");
printf("x >= %d", lft);
}
}