Terrible Sets
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 5330 | Accepted: 2715 |
Description
Let N be the set of all natural numbers {0 , 1 , 2 , . . . }, and R be the set of all real numbers. wi, hi for i = 1 . . . n are some elements in N, and w0 = 0.
Define set B = {< x, y > | x, y ∈ R and there exists an index i > 0 such that 0 <= y <= hi ,∑0<=j<=i-1wj <= x <= ∑0<=j<=iwj}
Again, define set S = {A| A = WH for some W , H ∈ R+ and there exists x0, y0 in N such that the set T = { < x , y > | x, y ∈ R and x0 <= x <= x0 +W and y0 <= y <= y0 + H} is contained in set B}.
Your mission now. What is Max(S)?
Wow, it looks like a terrible problem. Problems that appear to be terrible are sometimes actually easy.
But for this one, believe me, it‘s difficult.
Input
The input consists of several test cases. For each case, n is given in a single line, and then followed by n lines, each containing wi and hi separated by a single space. The last line of the input is an single integer -1, indicating the end of input. You may assume that 1 <= n <= 50000 and w1h1+w2h2+...+wnhn < 109.
Output
Simply output Max(S) in a single line for each case.
Sample Input
3 1 2 3 4 1 2 3 3 4 1 2 3 4 -1
Sample Output
12 14
Source
题意:给一排高度不同底部在同一水平线的连续矩形,在形成的总区域内寻找面积最大的矩形子区域。
思路一:枚举答案区域的最高点,也就是遍历所有小矩形,并以当前小矩形的高度为最终高度,找到左右方向课扩展的最大范围即可,复杂度n^2。因为太暴力了,没有写,据说可以过...
思路二:优化一下思路一,在寻找最大可扩展边界时,因为可扩展性是单调的,所以我们可以二分区间端点然后用某种数据结构求出区间最小值即可。我是二分+线段树,复杂度n*log^2。TLE了。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 int n; 45 struct rec { 46 ll w; 47 int h; 48 } R[50015]; 49 int mi[200015]; 50 void pushup(int i) {mi[i] = min(mi[i << 1], mi[i << 1 | 1]);} 51 void build(int i, int l, int r) { 52 if (l == r) { 53 mi[i] = R[l].h; 54 return; 55 } 56 int mi = l + r >> 1; 57 build(i << 1, l, mi); 58 build(i << 1 | 1, mi + 1, r); 59 pushup(i); 60 } 61 int query(int i, int l, int r, int x, int y) { 62 if (x <= l && r <= y) { 63 return mi[i]; 64 } 65 int res1 = MOD, res2 = MOD, mi = l + r >> 1; 66 if (x <= mi) res1 = query(i << 1, l, mi, x, y); 67 if (mi < y) res2 = query(i << 1 | 1, mi + 1, r, x, y); 68 return min(res1, res2); 69 } 70 int main() { 71 R[0].w = 0, R[0].h = -1; 72 while (~scanf("%d", &n) && ~n) { 73 ll ans = 0; 74 for (int i = 1; i <= n; ++i) { 75 scanf("%lld%d", &R[i].w, &R[i].h); 76 R[i].w += R[i - 1].w; 77 } 78 build(1, 0, n); 79 for (int i = 1; i <= n; ++i) { 80 int s1 = 0, e1 = i - 1, m1, res1 = i; 81 while (s1 <= e1) { 82 m1 = s1 + e1 >> 1; 83 if (query(1, 0, n, m1, i - 1) < R[i].h) { 84 s1 = m1 + 1; 85 } else { 86 e1 = (res1 = m1) - 1; 87 } 88 } 89 int s2 = i + 1, e2 = n, m2, res2 = i; 90 while (s2 <= e2) { 91 m2 = s2 + e2 >> 1; 92 if (query(1, 0, n, i + 1, m2) < R[i].h) { 93 e2 = m2 - 1; 94 } else { 95 s2 = (res2 = m2) + 1; 96 } 97 } 98 ans = max(ans, R[i].h * (R[res2].w - R[res1 - 1].w)); 99 } 100 printf("%lld\n", ans); 101 } 102 return 0; 103 }
思路三:维护一个高度递增的单调栈,每次新加入矩形时,弹出所有高度比他大的矩形同时求出弹出范围矩形所能形成的最大值。维护结束后再枚举栈内元素作为矩形区域左端点即可。复杂度O(n)。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 struct rec { 45 int w; 46 int h; 47 } R[50015]; 48 int n; 49 stack<int> sta; 50 int main() { 51 R[0].w = 0, R[0].h = -1; 52 sta.push(0); 53 while (~scanf("%d", &n) && ~n) { 54 for (int i = 1; i <= n; ++i) { 55 scanf("%d%d", &R[i].w, &R[i].h); 56 R[i].w += R[i - 1].w; 57 } 58 int ans = 0; 59 for (int i = 1; i <= n; ++i) { 60 int we = R[i - 1].w; 61 while (R[sta.top()].h >= R[i].h) { 62 int x = sta.top(); 63 sta.pop(); 64 int y = sta.top(); 65 ans = max(ans, R[x].h * (we - R[y].w)); 66 } 67 int x = sta.top(); 68 ans = max(ans, R[i].h * (R[i].w - R[x].w)); 69 sta.push(i); 70 } 71 int we = R[sta.top()].w; 72 while (sta.size() > 1) { 73 int x = sta.top(); 74 sta.pop(); 75 int y = sta.top(); 76 ans = max(ans, R[x].h * (we - R[y].w)); 77 } 78 printf("%d\n", ans); 79 } 80 return 0; 81 }
原文地址:https://www.cnblogs.com/BIGTOM/p/8468083.html