1. 程式人生 > >POJ 2082 題解

POJ 2082 題解

err ted 遍歷 scrip 區間 color case += bit

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-1
wj <= 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+w2
h2+...+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

Shanghai 2004 Preliminary 題意:給一排高度不同底部在同一水平線的連續矩形,在形成的總區域內尋找面積最大的矩形子區域。 思路一:枚舉答案區域的最高點,也就是遍歷所有小矩形,並以當前小矩形的高度為最終高度,找到左右方向課擴展的最大範圍即可,復雜度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 題解