Gym 101102D Rectangles 【单调栈】

Description

standard input/output

Given an R×C grid with each cell containing an integer, find the number of subrectangles in this grid that contain only one distinct integer; this means every cell in a subrectangle contains the same integer.

A subrectangle is defined by two cells: the top left cell (r1, c1), and the bottom-right cell (r2, c2) (1 ≤ r1 ≤ r2 ≤ R) (1 ≤ c1 ≤ c2 ≤ C), assuming that rows are numbered from top to bottom and columns are numbered from left to right.

Input

The first line of input contains a single integer T, the number of test cases.

The first line of each test case contains two integers R and C (1 ≤ R, C ≤ 1000), the number of rows and the number of columns of the grid, respectively.

Each of the next R lines contains C integers between 1 and 109, representing the values in the row.

Output

For each test case, print the answer on a single line.

Sample Input

Input
1
3 3
3 3 1
3 3 1
2 2 5
Output
16

求出由相同数字组成的矩形的个数

一看到这题就想到了这个题:

单调栈优化dp:hdu1506Largest Rectangle in a Histogram &hdu1505city game dp ||附面试题:柱子围水|柱子围面积

原题只是求最大的,对于维护的单调栈每次比较面积即可。而对于这个题,我们维护单调栈的值依旧是列序号。我们设ans[i][j]表示以(i,j)为右下角点的可组成矩阵个数,假设在(i,j)左边离它最近的高度比它小的位置是(i,p)那么ans[i][j]=ans[i][k]+(j-k)*h[i][j]。但是如果(i,j)和(i,k)不是同一种图案就不能加进去啦

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[1005][1005],ans[1005][1005],h[1005][1005];
int s[1005],pos[1005];
int main()
{
  //  freopen("cin.txt","r",stdin);
    int t,r,c;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&r,&c);
        memset(h,0,sizeof(h));
        memset(ans,0,sizeof(ans));
        memset(a,0,sizeof(a));
        for(int i=1;i<=r;i++)
        {
            for(int j=1;j<=c;j++)
            {
                scanf("%d",&a[i][j]);
                if(a[i-1][j]!=a[i][j])h[i][j]=1;
                else h[i][j]=h[i-1][j]+1;
            }
        }
        //for(int i=1;i<=r;i++){for(int j=1;j<=c;j++)printf("%d ",h[i][j]);puts(""); }
        int num;
        long long sum=0;
        for(int i=1;i<=r;i++)
        {
            for(int j=1;j<=c;j++)
            {
                if(a[i][j-1]!=a[i][j])
                {
                    num=1;
                    s[1]=j-1;//
                    h[i][j-1]=0;//
                    s[++num]=j;
                    //pos[j]=j-1;//
                    ans[i][j]=h[i][j];//
                    sum+=(long long)ans[i][j];
                }
                else
                {
                    while(h[i][j]<=h[i][s[num]])num--;
                    int p=s[num];
                    s[++num]=j;
                    ans[i][j]+=h[i][j]*(j-p);
                    if(h[i][p]!=0)ans[i][j]+=ans[i][p];
                    sum+=ans[i][j]*1LL;
                }
            }
        }
        printf("%I64d\n",sum);
    }
    return 0;
}


全部评论

相关推荐

07-11 22:27
中南大学 Java
程序员牛肉:学历的话没问题。但是没问题的也就只有学历了。 其实你的整体架构是正确的,博客接着干。但是项目有点过于简单了。从后端的角度上讲,你这也就是刚入门的水平,所以肯定约面试够呛。 如果你要应聘后端岗位,那你第一个项目竟然是仿写操作系统。这个你要面试官咋问你。你一定要记住一点,你简历上写的所有的东西,都是为了证明你有能力胜任当前的岗位,而不是为了证明你自己会什么。 如果你只是浅浅的做几个项目,描述也都是烂大街。技术点也都是各种混水类的配置类需求,那你就不要幻想自己能走多远。一定要保持思考,保持学习。
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务