获取子矩阵中不同元素的数量

时间:2013-12-22 06:53:04

标签: c arrays algorithm distinct-values

这是a problem from the December 2013 CodeChef Challenge,比赛已经结束。

问题陈述:

  

输入: n阶的矩阵和一个表示子矩阵的查询。

     

(x1, y1, x2, y2)

     

x1, y1表示左上角,x2, y2表示子矩阵的右下端。

     

输出:此子矩阵中不同元素的数量。

     

约束:

     
      
  • 时间限制= 1秒
  •   
  • 1≤N≤300
  •   
  • 1≤Q≤10^ 5
  •   
  • 1≤Ai,j≤10
  •   
  • 1≤X1≤X2≤N
  •   
  • 1≤Y1≤Y2≤N
  •   

这是我尝试过的:

#include<stdio.h>
//#include<conio.h>
int main()
{
  //clrscr();
  int a[300][300], test[100000], count[10], m, n, c, j, p, q, r, s;
  long qu, re, i;

  scanf("%d", &n);

  for (i = 0; i < n; i++)
  {
    for (j = 0; j < n; j++)
    {
      scanf("%d", &a[i][j]);
    }
  }

  scanf("%ld", &qu);
  for (re = 0; re < qu; re++)
  {
    c = 0;
    for(i = 0; i < 10; i++)
    {
      count[i] = 0;
    }

    scanf("%d %d %d %d", &p, &q, &r, &s);
    for (i = (p-1); i < r; i++)
    {
      for (j = (q-1); j < s; j++)
      {
        m = a[i][j];
        count[--m]++;
      }
    }

    for (i = 0; i < 10; i++)
    {
      if (count[i] != 0)
      {
        c++;
      }
    }
    test[re] = c;
  }

  for(i = 0; i < qu; i++)
  {
    printf("%d\n", test[i]);
  }

  //getch();
  return 0;
}

但我收到了TLE(超出时间限制)错误。

它必须对每个数字的累积频率做一些事情。

有人可以为这个问题建议一个有效的算法吗?

2 个答案:

答案 0 :(得分:1)

初始化并跟踪哈希映射。

遍历子矩阵的条目,并为每个条目

  • 检查它是否已经在哈希映射中;
  • 如果没有,请将total_distinct_entries递增1,然后将此条目添加到哈希映射中。

请参阅http://en.wikipedia.org/wiki/Hash_table

修改:另请参阅http://en.wikipedia.org/wiki/Set_data_structure,特别是有关实施的部分。在C ++中,标准库中提供了std::set数据结构。

答案 1 :(得分:1)

<强> EDITED

(使用基于1的索引)

首先尝试:

蛮力,将每个数字的计数存储在计数数组中,如问题海报所给出的那样,但这肯定会在很多测试用例上超时。

第二: 因为我们知道条目只能达到10我们可以尝试存储每个数字出现在子矩阵(1,1)到(i,j)中的次数。 假设该矩阵是Q.Q [i] [j] [k]给出k在i,j子矩阵中出现的次数。

这可以如下有效计算:

for i from 1 to n
    for j from 1 to n
       for k from 0 to 10
            Q[i][j][k] = Q[i-1][j][k] + Q[i][j-1][k] - Q[i-1][j-1][k]
       Q[i][j][A[i][j]]++

这可以在O(n ^ 2 *(k))时间内完成。由于k小于10,因此非常有效。

现在回答查询非常简单:

对于查询(x1,y1) - (x2,y2)

int count[10]
for k from 0 to 10
   // x is row and y is column
   count[k] = Q[x2][y2][k] - Q[x1-1][y2][k] - Q[x2][y1-1][k] + Q[x1-1][y1-1][k]

这回答了O(k)时间内的所有查询。因为k是0到10.它完全在时间限制内。