您的位置:首页 > 其它

Gym 101102D Rectangles 【单调栈】

2016-10-04 11:03 232 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: