zoukankan      html  css  js  c++  java
  • 紫书 例题8-19 UVa 12265 (扫描法+单调栈)

    首先可以用扫描法处理出一个height数组, 来保存从当前行开始, 每一个格子可以向上延伸的最大长度。

    这种“延伸”的问题用扫描法, 因为往往这个时候可以利用前一次的结果来更新当前的值


    然后这道题的关键就是是维护一个单调栈, 栈顶的元素就是当前状态所求的答案。

    这个单调栈满足的性质是:c从小到大增加, h从小到大增加, h-c从小到大增加。c表示当前列, h表示height[c]

    因为遍历的时候是从左到右的, 所以c就是一直增大的, 然后加入的时候有个while循环, 保证h是一直增大的,

    最后加入的时候的if就是维护h-c是一直增大的。


    这道题和防线那道题目很像, 都是维护一个双重有序的结构, 在加入新的元素的时候需要修改结构的值。只不过那道题是二分,这道题是单调栈。


    #include<cstdio>
    #include<cstring>
    #define REP(i, a, b) for(int i = (a); i < (b); i++)
    using namespace std;
    
    const int MAXN = 1123;
    char s[MAXN][MAXN];
    int height[MAXN], ans[MAXN<<1], n, m, top;
    
    struct node
    {
    	int c, h;
    	int val() { return h - c; }
    	node(int c = 0, int h = 0) : c(c), h(h) {}
    }stack[MAXN];
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	
    	while(T--)
    	{
    		scanf("%d%d", &n, &m);
    		REP(i, 0, n) scanf("%s", s[i]);
    		
    		memset(height, 0, sizeof(height));
    		memset(ans, 0, sizeof(ans));
    		
    		REP(i, 0, n)
    		{
    			top = -1;
    			REP(j, 0, m)
    			{
    				if(s[i][j] == '#')
    				{
    					top = -1;
    					height[j] = 0;
    					continue;
    				}
    				
    				height[j]++;
    				node r(j, height[j]);
    				if(top < 0)  stack[++top] = r;     
    				else
    				{
    					while(top >= 0 && r.h <= stack[top].h) r.c = stack[top--].c;
    					if(top < 0 || r.val() > stack[top].val()) stack[++top] = r;
    				}
    
    				ans[j+stack[top].val()+1]++;
    			}
    		}
    		
    		REP(i, 1, n + m + 1)
    			if(ans[i])
    				printf("%d x %d
    ", ans[i], i * 2);
    	}
    	
    	return 0;
    }

  • 相关阅读:
    php 注册与登录
    php 多条件查询
    php(ajax)异步刷新(转)
    PHP中的6种加密方式
    ajax 异步刷新,需要填写的参数
    php+Mysql 页面登录代码
    php+Mysql页面注册代码
    jquery入门知识点总结(转)
    php+Mysql中网页出现乱码的解决办法详解
    php代码常见错误详解整理
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819582.html
Copyright © 2011-2022 走看看