Description
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
1 3 3 3 3 1 3 3 1 2 2 5
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;
}