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 }