CFGym - 101102D.Rectangles 单调栈+dp优化

来源:互联网 发布:php钓鱼源码 编辑:程序博客网 时间:2024/06/05 22:48

1.     题目描述:

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

A subrectangle isdefined 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 numberedfrom left to right.

Input

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

The first line ofeach 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 thenext R lines contains C integers between 1 and 109,representing the values in the row.

Output

For each testcase, print the answer on a single line.

Example

Input

1
3 3
3 3 1
3 3 1
2 2 5

Output

16

2.     题意概述:

给你一个RxC矩阵,里面每一个矩阵元素中有一个数在1~1e9之间,求有多少个子矩阵里面的所有数相同?

3.     题解思路:

先对每一列从上到下遍历,用h[i][j]记录从当前元素往上最多有多少数相同, 然后对每一行遍历,用ans[i][j] 记录以a[i][j]为右下角的元素的子矩阵个数,那么我们可以发现:设当前元素之前同一行中小于它且最近的元素为a[i][k] 那么ans[i][j]=ans[i][k]+(j-k)*h[i][j]为了降低复杂度可以在当前行从左向右遍历的过程中把各列的高放入单调栈中,这样可以快速知道小于当前元素最近的元素的位置,最后对ans[][]求和就是结果 ;

4.     Ac代码:

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <algorithm>#include <functional>#include <cmath>#include <vector>#include <queue>#include <map>#include <set>#include <ctime>#define INF 0x7fffffff#define maxn 1111#define eps 1e-6#define pi acos(-1.0)#define e 2.718281828459#define mod (int)1e9 + 7;using namespace std;typedef long long ll;int a[maxn][maxn], h[maxn][maxn], p[maxn][maxn], s[maxn * maxn];int main(){#ifndef ONLINE_JUDGE  freopen("in.txt", "r", stdin);  freopen("out.txt", "w", stdout);  long _begin_time = clock();#endif  int r, c, t;  scanf("%d", &t);  while (t--)  {    memset(h, 0, sizeof(h));    memset(s, 0, sizeof(s));    memset(p, 0, sizeof(p));    scanf("%d%d", &r, &c);    for (int i = 1; i <= r; i++)      for (int j = 1; j <= c; j++)      {        scanf("%d", &a[i][j]);        h[i][j] = a[i][j] == a[i - 1][j] ? h[i - 1][j] + 1 : 1;      }    int cnt =1;    ll ans = 0;    for (int i = 1; i <= r; i++)      for (int j = 1; j <= c; j++)      {        if (a[i][j - 1] != a[i][j]) //不等则求之        {          cnt = 1;          s[1] = j - 1; // 单调栈初始化          h[i][j - 1] = 0;  //无法延伸          s[++cnt] = j;          p[i][j] = h[i][j];          ans += 1LL * p[i][j]; // 防爆        }        else // 等则并之        {          while (h[i][j] <= h[i][s[cnt]]) // 单调栈求比他小的第一个位置,顺便把大的元素全部出栈            cnt--;          int pos = s[cnt];               // 记录下来          s[++cnt] = j;                   //入栈          p[i][j] += h[i][j] * (j - pos); // 求出来记录之          if (h[i][pos] != 0)            p[i][j] += p[i][pos];          ans += 1LL * p[i][j];        }      }    printf("%lld\n", ans);  }#ifndef ONLINE_JUDGE  long _end_time = clock();  printf("time = %ld ms\n", _end_time - _begin_time);#endif  return 0;}

0 0
原创粉丝点击