• Hihocoder1673


    这个题还是挺有意思的,得发现点性质,然后才能知道要怎么搞。

    首先我们得知道这个合法段是连一起的,这个是一个很重要的一点,我们得知道如果10101010  可以,那么他的所有子段都是可以的。。。。。。。

    这个应该是很好发现的?    (那怎么才能发现这一点呢??????)   我们首先应该对单行分析,分析一下单行怎么搞,因为单行是矩阵的基础,然后考虑先填1010,这样搞,发现这个段的性质   这个手玩一下样例就可以了,很好发现的

    (事实证明手玩样例是很重要的,很多题目都是手玩样例出来的)

    这个的话我们可以通过手玩确定出来很好的性质,比如那道cf 的  d和这道

    然后我们可以通过预处理知道当前这个点向上能衍生的最长长度的长度

    然后根据上面的性质分成一个个的段,然后再这个段里面通过单调栈操作

    下面是代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cmath>
     6 #include <bitset>
     7 #include <stack>
     8 typedef long long ll;
     9 using namespace std;
    10 const int maxn=2100;
    11 int n,m;
    12 char s[maxn][maxn];
    13 int h[maxn][maxn];
    14 int li[maxn][maxn];
    15 int siz[maxn];
    16 stack<int> sta;
    17 int main(){
    18     scanf("%d%d",&n,&m);
    19     for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    20     for(int i=1;i<=n;i++){
    21         for(int j=1;j<=m;j++){
    22             if(i==1) h[i][j]=1;
    23             else{
    24                 if(s[i][j]!=s[i-1][j]) h[i][j]=h[i-1][j]+1;
    25                 else h[i][j]=1;
    26             }
    27         }
    28     }
    29 
    30     int ans=0;
    31     for(int i=1;i<=n;i++){
    32         int l,r;
    33         for(int j=1;j<=m;j=r+1){
    34             l=j;r=j;
    35             for(int k=j+1;k<=m;k++){
    36                 if(s[i][k]!=s[i][k-1]) r=k;
    37             }
    38             for(int k=l;k<=r;k++) li[i][k]=h[i][k],siz[k]=1;
    39             li[i][r+1]=0;li[i][l-1]=0;
    40             while(!sta.empty()) sta.pop();
    41             sta.push(l-1);
    42             for(int k=l;k<=r+1;k++){
    43                 if(li[i][k]>=li[i][sta.top()]){
    44                     sta.push(k);
    45                 }else{
    46                     int len=0;
    47                     while(!sta.empty()&&li[i][k]<li[i][sta.top()]){
    48                         len+=siz[sta.top()];
    49                         ans=max(ans,len*li[i][sta.top()]);
    50                         sta.pop();
    51                     }
    52                     sta.push(k);siz[k]+=len;
    53                 }
    54             }
    55         }
    56     }
    57     printf("%d
    ",ans);
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    字符统计和滑动窗口
    字典树应用及用哈希表代替
    迷宫里的动态规划应用
    求所有排列中的第 i 个排列的问题
    最大子串和问题
    二分查找、变形及应用
    前 n 个数原址排序的问题
    LeetCode 32 括号匹配
    11.常用的API
    10.正则表达式
  • 原文地址:https://www.cnblogs.com/pandaking/p/12113512.html
Copyright © 2020-2023  润新知