POJ 2082 题解

Posted hit_yjl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2082 题解相关的知识,希望对你有一定的参考价值。

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 }

 

以上是关于POJ 2082 题解的主要内容,如果未能解决你的问题,请参考以下文章

POJ2082 Terrible Sets

POJ 2082 Terrible Sets

poj2082 terrible sets 单调栈

poj2082 terrible sets 单调栈

题解 poj3057 Evacuation

POJ 2777-题解