Gym - 101102D Rectangles (单调栈)

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.

Example

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

题意:问由单一数字组成的矩阵的个数。
思路:
dp[i][j]表示以位置i,j为右下角的矩阵个数。
先处理出当前位置向上延伸相同的数字最高有多高。用num[i]记录。
用单调栈处理出在此之前的,第一个小于自己的num[i].
判断中间有没有插入别的数,再进行处理。详见solve函数。
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define debug(a,i) cout<<#a<<"["<<i<<"] = "<<a[i]<<endl;
14 #define ls (t<<1)
15 #define rs ((t<<1)|1)
16 using namespace std;
17 typedef long long ll;
18 typedef unsigned long long ull;
19 const int maxn = 1024;
20 const int maxm = 100086;
21 const int inf = 2.1e9;
22 const ll Inf = 999999999999999999;
23 const int mod = 1000000007;
24 const double eps = 1e-6;
25 const double pi = acos(-1);
26 int n,m;
27 int mp[maxn][maxn];
28 int num[maxn];
29 ll ans;
30 struct  node{
31     int num,pos;
32 };
33 stack<node>st;
34 int pre[maxn];
35 int pre1[maxn];
36 ll dp[maxn];
37 void solve(int t){
38     memset(dp,0,sizeof(dp));
39     memset(pre,0,sizeof(pre));
40     while(!st.empty()){
41         st.pop();
42     }
43     num[0]=-1;
44     for(int i=m;i>=0;i--){
45         while(!st.empty()&&st.top().num>num[i]){
46             pre[st.top().pos]=i;
47             st.pop();
48         }
49         st.push(node{num[i],i});
50     }
51     int k=1;
52     for(int i=1;i<=m;i++){
53         if(mp[t][i]!=mp[t][i-1]){
54             k=i;
55         }
56         pre1[i]=k;
57     }
58     int pree;
59     for(int i=1;i<=m;i++){
60         if(pre1[i]>pre[i]){
61             dp[i]=1ll*num[i]*(i-pre1[i]+1);
62             ans+=dp[i];
63         }
64         else{
65             dp[i]=1ll*num[i]*(i-pre[i])+dp[pre[i]];
66             ans+=dp[i];
67         }
68     }
69 }
70 
71 int main()
72 {
73     int T;
74     scanf("%d",&T);
75     while(T--){
76         scanf("%d%d",&n,&m);
77         for(int i=1;i<=n;i++){
78             for(int j=1;j<=m;j++){
79                 scanf("%d",&mp[i][j]);
80             }
81         }
82         ans=0;
83         memset(num,0,sizeof(num));
84         for(int i=1;i<=n;i++){
85             for(int j=1;j<=m;j++){
86                 if(mp[i][j]==mp[i-1][j]){
87                     num[j]++;
88                 }
89                 else{
90                     num[j]=1;
91                 }
92             }
93             solve(i);
94         }
95         printf("%lld\n",ans);
96     }
97     return 0;
98 }
View Code

posted @ 2019-05-06 20:17  断腿三郎  阅读(335)  评论(0编辑  收藏  举报