zoukankan      html  css  js  c++  java
  • P4147 玉蟾宫--单调栈

    P4147 玉蟾宫

    题目背景

    有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。

    题目描述

    这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda。

    现在freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'并且面积最大。

    但是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为S,它们每人给你S两银子。

    输入输出格式

    输入格式:

    第一行两个整数N,M,表示矩形土地有N行M列。

    接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。

    输出格式:

    输出一个整数,表示你能得到多少银子,即(3*最大'F'矩形土地面积)的值。

    输入输出样例

    输入样例#1: 
    5 6 
    R F F F F F 
    F F F F F F 
    R R R F F F 
    F F F F F F 
    F F F F F F
    输出样例#1: 
    45

    这是一道非常经典的题目。看到学长们个个都用悬线法来做,无奈本蒟蒻水平过低,只会用单调栈来切这道题。

    我们可以把F看做1,R看做0。

    来看下面这个矩阵:

    看起来这道题似乎无从下手,但是如果我们把每一列1的连续和求出来,像这样:

    也许我们仍然没能发现什么规律,但是不要紧,我们接着看:

                  

           

    我们尝试以每一行作为这个矩形的底边,找出图中最大的矩形,也就是图中的染色部分,有没有想起点什么?

     这不就是poj 2559 Largest Rectangle in a Histogram 这道题吗?这样我们的思路也就得出了,我们可以先对读入的数据预处理一下,统计每一列的连续和,然后对每一行维护一个单调栈,求出以每一行为底的最大矩阵的大小,最后取最大值。

      1 #include<stack>
      2 #include<cstdio>
      3 #include<string>
      4 #include<cstring>
      5 #include<queue>
      6 #include<cmath>
      7 #include<algorithm>
      8 #include<map>
      9 #include<iostream>
     10 #define maxn 1005
     11 using namespace std;
     12 
     13 stack<int>s;
     14 
     15 inline int read()
     16 {
     17     char c=getchar();
     18     int res=0,x=1;
     19     while(c<'0'||c>'9')
     20     {
     21         if(c=='-')
     22         x=-1;
     23         c=getchar();
     24     }
     25     while(c>='0'&&c<='9')
     26     {
     27         res=res*10+(c-'0');
     28         c=getchar();
     29     }
     30     return x*res;
     31 }
     32 
     33 long long ans;
     34 int n,m,a[maxn],w[maxn];
     35 int ju[maxn][maxn];
     36 char aa;
     37 
     38 int main()
     39 {
     40     n=read();m=read();
     41     for(int i=1;i<=n;i++)
     42     {
     43         for(int j=1;j<=m;j++)
     44         {
     45             scanf("%s",&aa);
     46             if(aa=='F')
     47             {
     48                 ju[i][j]=1;
     49             }
     50             if(aa=='R')
     51             {
     52                 ju[i][j]=0;
     53             }
     54         }
     55     }
     56     for(int j=1;j<=m;j++)
     57     {
     58         for(int i=1;i<=n;i++)
     59         {
     60              if(ju[i][j]==1)
     61              {
     62                  ju[i][j]=ju[i-1][j]+1;
     63             }
     64             else
     65             {
     66                 ju[i][j]=0;
     67             }
     68         }
     69     }
     70     for(int i=1;i<=n;i++)
     71     {
     72         for(int j=1;j<=m;j++)
     73         {
     74             a[j]=ju[i][j];
     75         }
     76         a[1+m]=0;
     77         while(s.size()) s.pop();
     78         for(int j=1;j<=m+1;j++)
     79         {
     80             if(s.empty()||a[j]>=s.top())
     81             {
     82                 s.push(a[j]);
     83                 w[s.size()]=1;
     84             }
     85             else
     86             {
     87                 int mi=0;
     88                 while(!s.empty()&&a[j]<s.top())
     89                 {
     90                     mi+=w[s.size()];
     91                     ans=max(ans,(long long)mi*s.top());
     92                     s.pop();
     93                 }
     94                 s.push(a[j]);
     95                 w[s.size()]=mi+1;
     96             }
     97         }
     98     }
     99     printf("%lld
    ",ans*3);
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    「Vue」nrm
    「Vue」路由
    「Vue」父子组件之间的传值及调用方法
    「Vue」vue生命周期
    「Vue」自定义指令
    「Vue」自定义按键修饰符
    「Vue」过滤器
    常用断点设置
    BUUCTF 不一样的flag writeup
    好久没有写东西,最近在看逆向相关的东西,做点记录
  • 原文地址:https://www.cnblogs.com/snowy2002/p/10288279.html
Copyright © 2011-2022 走看看