有一个w*h的矩形,每次对它横着切一刀,或者竖着切一刀,每一刀切完之后,有若干个矩形会被分成两个更小的矩形。每一刀切完之后,请找出所有矩形中面积最大的。
输入
第一行是三个整数w h n表示矩形的宽度和高度,以及操作的数量
接下来n行每行一个操作
是下列两种形式之一:
H y (表示横着在离矩形下边界y的位置切一刀)
V x(表示竖着在离矩形左边界x的位置切一刀)
2 \le w, h \le 200000, 1 \le n \le 2000002≤ w,h≤ 200000,1≤ n≤ 200000
1 ≤ y ≤ h - 1,1 ≤ x ≤ w - 1
输出
每次操作之后输出一行,表示当前最大矩形的面积。
样例
输入
复制
4 3 4 H 2 V 2 V 3 V 1
输出
复制
8 4 4 2
输入
复制
7 6 5 H 4 V 3 V 5 H 2 V 1
输出
复制
28 16 12 6 4
提示
子任务1,20分,1 \le n \le 1001≤ n≤ 100
子任务2,80分,全范围
横着切和竖着切互不影响,我们每次只需要找出最大的宽和最大的高相乘就可以了,可以用优先队列,但是对于被切割的块又不能准确定位,可以用set记录切刀的位置,当队列头部被切割过时再进行更新。
#pragma warning(disable:4996) #include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <set> #include <algorithm> #include <functional> #define inf 0x3f3f3f3f int main() { int w, h, n; char op[2]; int d; std::priority_queue < std::pair<int, int>, std::vector<std::pair<int, int>>, std::less<std::pair<int, int>>> qr, qc; scanf("%d%d%d", &w, &h, &n); qr.push(std::make_pair(h, 0)); qc.push(std::make_pair(w, 0)); std::set<int> cutR, cutC; cutR.insert(0); cutR.insert(h); cutC.insert(0); cutC.insert(w); for (int i = 0; i < n; i++) { scanf("%s%d", op, &d); if (op[0] == 'V') { cutC.insert(d); } else { cutR.insert(d); } bool flag = true; while (flag) { int l = qr.top().second; int r = l + qr.top().first; std::set<int>::iterator it = cutR.lower_bound(l); while (*it != r) { if (*it != l) { qr.push(std::make_pair(*it - l, l)); l = *it; } it++; } if (l != qr.top().second) { qr.push(std::make_pair(*it - l, l)); qr.pop(); } else { flag = false; } } flag = true; while (flag) { int l = qc.top().second; int r = l + qc.top().first; std::set<int>::iterator it = cutC.lower_bound(l); while (*it != r) { if (*it != l) { qc.push(std::make_pair(*it - l, l)); l = *it; } it++; } if (l != qc.top().second) { qc.push(std::make_pair(*it - l, l)); qc.pop(); } else { flag = false; } } printf("%lld\n", (long long)qr.top().first * qc.top().first); } return 0; }