CodeForcescode
橫着切和豎着切是互相不影響的。get
假設如今橫着切成了不少段,顯然此時面積最大的矩形的一邊長就是這些段中長度最長的一段。豎着切的也是同樣的。string
因此就能夠用$set$來維護切過的橫、縱座標與每一段的長度。it
修改時,先找到相鄰的兩刀,再找到對應的長度,刪去這個長度,再加入切出來的兩個新的長度。io
一開始要把$\mathbf W$、$\mathbf H$這些東西加進去。class
#include <set> #include <cstdio> #include <cstring> #include <algorithm> using std::min; using std::max; using std::sort; using std::swap; using std::unique; using std::lower_bound; using std::set; typedef long long ll; template<typename T> void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); } while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag; } const int _ = 2e5 + 10; int W, H, n, w[_], h[_]; int main () { read(W), read(H), read(n); set<int> sw, sh, qw, qh; sw.insert(W), sw.insert(-W); sh.insert(H), sh.insert(-H); qw.insert(0), qw.insert(W), qw.insert(-W); qh.insert(0), qh.insert(H), qh.insert(-H); ++w[W], ++h[H]; char ch[3]; int x; for(int i = 1; i <= n; ++i) { scanf("%s%d", ch, &x); if(ch[0] == 'H') { qh.insert(x), qh.insert(-x); int r = *(qh.upper_bound(x)); int l = -*(qh.upper_bound(-x)); if(h[r - l]) --h[r - l]; if(!h[r - l]) sh.erase(r - l), sh.erase(l - r); sh.insert(x - l), ++h[x - l]; sh.insert(r - x), ++h[r - x]; sh.insert(l - x), sh.insert(x - r); } else { qw.insert(x), qw.insert(-x); int r = *(qw.upper_bound(x)); int l = -*(qw.upper_bound(-x)); if(w[r - l]) --w[r - l]; if(!w[r - l]) sw.erase(r - l), sw.erase(l - r); sw.insert(x - l), ++w[x - l]; sw.insert(r - x), ++w[r - x]; sw.insert(l - x), sw.insert(x - r); } set<int>::iterator r1, r2; r1 = sh.begin(), r2 = sw.begin(); printf("%lld\n", (ll)(*r1) * (*r2)); } return 0; }