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

C 获取子矩阵中不同元素的数量,c,arrays,algorithm,distinct-values,C,Arrays,Algorithm,Distinct Values,比赛到此结束 问题陈述: 输入:n阶方阵和表示子矩阵的查询 (x1,y1,x2,y2) x1,y1表示子矩阵的左上端,x2,y2表示子矩阵的右下端 输出:此子矩阵中不同元素的数量 约束条件: 时间限制=1秒 一,≤ N≤ 三百 一,≤ Q≤ 10^5 一,≤ 哎,j≤ 十, 一,≤ X1≤ X2≤ N 一,≤ Y1≤ Y2≤ N 这就是我尝试过的: #include<stdio.h> //#include<conio.h> int main() { //clrsc

比赛到此结束

问题陈述:

输入:n阶方阵和表示子矩阵的查询

(x1,y1,x2,y2)

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

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

约束条件:

  • 时间限制=1秒
  • 一,≤ N≤ 三百
  • 一,≤ Q≤ 10^5
  • 一,≤ 哎,j≤ 十,
  • 一,≤ X1≤ X2≤ N
  • 一,≤ 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;
}
#包括
//#包括
int main()
{
//clrsc();
INTA[300][300],测试[100000],计数[10],m,n,c,j,p,q,r,s;
龙曲,热,我;
scanf(“%d”和“&n”);
对于(i=0;i
但我有一个TLE(超过时间限制)错误

它必须与每个数字的累积频率有关


有人能为这个问题提出一个有效的算法吗?

初始化并跟踪哈希映射

迭代子矩阵的条目,对于每个条目

  • 检查它是否已经在哈希映射中
  • 如果不是,则将
    total_distinct_entries
    增加1,并将此项添加到哈希映射中


编辑:另请参见,特别是关于实现的部分。在C++中,标准库中有“<代码> STD::SET//COD>数据结构”。

< P> <强>编辑<强> < /P> (使用基于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)


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

您的代码应该适当缩进,以便于我们阅读。此外,您应该使用更有意义的变量名,而不是一个或两个字母的变量名。您似乎假设矩阵将只包含0到9的整数。但你的问题中没有提到这一点!散列映射的效率实际上不如OP当前的效率。请注意,问题中的代码只在目标区域循环一次,执行两行非常简单的代码。@Dukeling是这样的;OP的“解决方案”假定矩阵条目在
[1,10]
范围内,而他在原始帖子中没有说明这一点。我同意他的解决方案比一个带有这个附加约束的哈希映射更快,但有了这个附加约束,似乎真的没有比他拥有的更好的解决方案了,除了…(续)…看起来(从他的解决方案中回溯)问题是,他会得到一些相同矩阵的子矩阵集合,而他优化解决方案的方式是在迭代之间缓存信息。当然,在他的问题描述中没有提到这些。@gustav bertram这里没有假设,我不想破坏他的整个问题。codechef.com/viewsolution/3102585由于原始海报的解决方案没有针对
N=300 Q=100000(X1,Y1,X2,Y2)=(1,1300300)
输入进行充分优化,您是否介意发布您的解决方案及其工作原理?这是一个非常令人印象深刻的答案!谢谢你的发帖。关于破坏问题-堆栈溢出,你不应该为懒惰的人做工作,但是没有任何为某人破坏问题的概念。如果你能很容易地完整地回答一个问题,你应该。它不仅是为了帮助最初的提问者,也是为了帮助今天之后阅读问答的每个人。
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]