1. 程式人生 > >Codeforces Gym 101190 (NEERC 2016) H. Hard Refactoring (模擬 + 樹狀陣列)

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

215(−32768) to 2151(32767) inclusive.

解題思路

簡單模擬,數字區間為 [215,2151] ,全取為 true ,全不取為 false 。否則按最簡表示式給出範圍。

對於輸入給的表示式,讀取其表示的區間 [l, r] ,若 l <= r ,則將其在一維數軸上 [l, r] 每個數 +1

對結果判斷,[215,2151] 區間的每個數字判斷其是否能夠取到,併合並區間,列印若干段不連續區間即可。

對於如何快速對區間修改及單點查詢,通過樹狀陣列即可。

程式碼

#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); } }