UVa 12265 (单调栈) Selling Land

紫书上分析了很多很多,超详细,= ̄ω ̄=

每扫描一行可以计算一个height数组,表示从这块空地向上延伸多少块空地,而且这个数组可以逐行递推。

首先对于每一行来说维护一个单调栈,栈里放的是矩形的左上角,而且横坐标c和高度h也都是递增的,另外对于扫描到的同一个右下角,矩形面积的大小只与左上角的横坐标c和高度h的差值h-c有关,所以栈里面的h-c也都是递增的。

另外,计算出来当前的height[j]的时候有可能会“削减”栈中的矩形。

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int maxn = 1000 + 10;
 6 char s[maxn][maxn];
 7 
 8 int height[maxn], ans[maxn << 1];
 9 
10 struct Rect
11 {
12     int c, h;
13     Rect(int c = 0, int h = 0):c(c), h(h) {}
14 }rect[maxn];
15 
16 int n, m;
17 
18 int main()
19 {
20     //freopen("in.txt", "r", stdin);
21 
22     int T; scanf("%d", &T);
23     while(T--)
24     {
25         scanf("%d%d", &n, &m);
26         for(int i = 0; i < n; i++) scanf("%s", s[i]);
27 
28         memset(height, 0, sizeof(height));
29         memset(ans, 0, sizeof(ans));
30 
31         for(int i = 0; i < n; i++)
32         {
33             int top = -1;
34             for(int j = 0; j < m; j++)
35             {
36                 if(s[i][j] == '#')
37                 {
38                     top = -1;
39                     height[j] = 0;
40                 }
41                 else
42                 {
43                     height[j]++;
44                     Rect r(j, height[j]);
45                     if(top < 0) rect[++top] = r;    //空栈直接入栈
46                     else
47                     {
48                         while(top >= 0 && rect[top].h >= r.h) r.c = rect[top--].c; //栈中的h应小于height[j]
49                         if(top < 0 || r.h - r.c > rect[top].h - rect[top].c) rect[++top] = r;
50                     }
51                     r = rect[top];
52                     ans[r.h + j - r.c + 1]++;
53                 }
54             }
55         }
56         for(int i = 2; i <= m + n; i++) if(ans[i]) printf("%d x %d\n", ans[i], i * 2);
57     }
58 
59     return 0;
60 }
代码君

 

posted @ 2015-04-29 14:59  AOQNRMGYXLMV  阅读(288)  评论(0编辑  收藏  举报