c++ - 如何减少这个问题的执行时间(即更快的代码)

标签 c++ c time performance execution

这个问题来自 Codechef.com [如果有人仍在解决这个问题,请在尝试之前不要进一步查看该帖子],虽然它运行正确,但我需要使其更快。我是 c 初学者,c++。(我知道数组、字符串和指针,但不知道文件处理等)。那么有没有一种方法可以使这个程序运行得更快而不使其变得复杂(如果算法复杂也可以)。 如果你提到你遵循哪本书,我也会接受复杂的编码:)。 我目前正在关注罗伯特·拉福尔。 这是程序:-

有 N 个数字 a[0],a[1]..a[N - 1]。最初都是 0。您必须执行两种类型的操作:

1) 将索引 A 和 B 之间的数字加 1。这由命令“0 A B”表示

2) 回答索引 A 和 B 之间有多少个数可以被 3 整除。这用命令“1 A B”表示。

输入:

第一行包含两个整数,N 和 Q。接下来的 Q 行的每一行的形式都是“0 A B”或“1 A B”,如上所述。

输出:

为“1 A B”形式的每个查询输出 1 行,其中包含相应查询所需的答案。

示例输入:

4 7
1 0 3
0 1 2
0 1 3
1 0 0
0 0 3
1 3 3
1 0 3

示例输出:

4
1
0
2

约束:

1 <= N <= 100000
1 <= Q <= 100000
0 <= A <= B <= N - 1

这是我的解决方案:-

#include<stdio.h>

int main()
{
    unsigned int n; //amount of numbers taken
    scanf("%u",&n);

    unsigned int arr[n],q,a,b,count=0,j,i;
    short int c;
    scanf("%u",&q);//cases taken  
    for(i=0;i<n;++i)
    {
      arr[i]=0;
    }    


    for(i=0;i<q;++i)
    {
      scanf("%d%u%u",&c,&a,&b);//here a,b are A and B respectively and c is either 
                               //o or 1

      if(c==0)
      {
        for(j=a;j<=b;++j)
          arr[j]++;
      }


      if(c==1)
      {
        for(j=a;j<=b;++j)
        {
          if(arr[j]%3==0)
            count++;
        }
       printf("%u\n",count);
      }
      count=0;
    }  

}

最佳答案

1) Increase the numbers between indices A and B by 1. This is represented by the command "0 A B"

2) Answer how many numbers between indices A and B are divisible by 3. This is represented by the command "1 A B".

最初的数字是 0,因此可以被 3 整除。增加 1 使数字不可整除。下一个增量 - 数字仍然不可整除。第三次增量使数字再次整除。

可以尝试的第一个优化是不要让数字增长到 2 以上:如果在增量期间数字从 2 变为 3,请将其设置回零。现在搜索范围变成与 0 的简单比较。(这样数组将包含而不是其模 3 的数字。)

第二个优化是使用范围而不是普通数组,例如类似于RLE的东西:将具有相同整除性的所有相邻数字折叠成一个范围。该数组将包含如下结构,而不是数字:

struct extent {
   int start; /* 0 .. N-1; extent should have at least one number */
   int end;   /* 0 .. N   */
   int n;     /* 0, 1, 2; we are only interested in the result of % */
};

最初,该数组将包含覆盖所有数字的单个范围 {0, N, 0} 。在增量步骤期间,一个范围可能会被分割或与相邻的范围合并。这种表示会加快数字的计数,因为您不是逐一而是分块地遍历数组。 (如果所有范围仅包含一个元素,它仍然会降级为线性搜索。)


另一种方法可能是使用三个带有下标的集合来代替数组。集合#0将包含模3为0的所有数字的下标,集合#1 - 1,集合#2 - 2。因为在增量操作期间,我们需要进行搜索,而不是std::set。最好使用例如 std::bitset 每个位都标记属于该集合的数字的索引。

注意这样我们就根本不保留原始数字。我们隐式地只保留模 3 的结果。

在增量过程中,我们需要找到索引属于哪个集合,例如设置 #n,并将索引移动到下一个 (mod 3) 集合:将集合中的位设置为零 n ,将集合 n + 1 (mod 3) 中的位设置为 1 。现在,计算可被 3 整除的数字就像计算集合 #0 中的非零位一样简单。这可以通过创建一个临时 std::bitset 来完成。作为位范围为 [A,B] 的掩码设置为 1,使用临时集屏蔽 #0 并调用 std::bitset::count()在生成的位集上。

关于c++ - 如何减少这个问题的执行时间(即更快的代码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3645712/

相关文章:

java - 在 Java 中将以毫秒为单位的日期转换为今天、昨天、过去 7 天、过去 30 天

c++ - 我如何在 C++ 中将数字读入输出文件

带有 STM32CubeMX 的 C++ 和用于 STM32 AC6 工具的 Eclipse System Workbench

C++(cilk加代码): Segmentation fault 11

c - ISR 中的事件通知

C 程序写入目录内容

algorithm - 计算循环的运行时间

c++ - 为什么 mktime 为我的 std::tm 返回 -1

c++ - 无法使用 lldb 和 VSCode 调试简单的 C++ 程序

c - 正则表达式:匹配c中的 float