【发布时间】:2010-09-01 16:22:14
【问题描述】:
这是一个竞赛 Q:
有 N 个数 a[0],a[1]..a[N - 1]。最初都是 0。你必须执行两种类型的操作:
- 将索引 A 和 B 之间的数字增加 1。这由命令“0 A B”表示
- 回答索引 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
我不知道如何解决这个问题。你能帮忙吗?
时间限制为 1 秒。我尝试了蛮力,我还尝试为每个 i 保存第 i 个元素之前的 3 除数。
这是我的 C 代码:
#include <stdio.h>
int nums[100*1000+20];
int d[100*1000+20];
int e[100*1000+20];
int dah[100*1000+20];
int main()
{
int n,q;
scanf("%d%d",&n,&q);
int h;
for(h=0;h<n;h++)
{d[h/100]++; e[h/1000]++; dah[h/10]++;}
int test;
for(test=0;test<q;test++)
{
int op,start,end;
scanf("%d%d%d",&op,&start,&end);
if(0==op)
{
int x;
for(x=start;x<=end;x++)
{
nums[x]++;
nums[x]%=3;
if(nums[x]==0)
{
d[x/100]++;
e[x/1000]++;
dah[x/10]++;
}
else if(nums[x]==1)
{
d[x/100]--;
e[x/1000]--;
dah[x/10]--;
}
}
}
else if(1==op)
{
int f;
int ans=0;
for(f=start;f<=end;)
{
if(f%1000==0&&f+1000<end)
{
ans+=e[f/1000];
f+=1000;
}
else if(f%100==0&&f+100<end)
{
ans+=d[f/100];
f+=100;
}
else if(f%10==0&&f+10<end)
{
ans+=dah[f/10];
f+=10;
}
else
{
ans+=(nums[f]==0);
f++;
}
}
printf("%d\n",ans);
}
}
return 0;
}
在这种方法中,我在 k*1000 和 (k+1)*1000 之间保存了 3 的倍数,对于 k*100 和 (k+1)*100 以及 10 也是如此。这对我有帮助查询更快。但这仍然让我超出了时间限制。
【问题讨论】:
-
您能否重新格式化以提高可读性?
-
@jer - 作业问题在这里有效且合法。我们通过提供提示而不是完整的答案来回答它们。
-
@Oded:对不起,我是新来的。不知道该怎么办。 @justkt:我尝试了蛮力,还尝试保存每个 i 在第 i 个元素之前有多少个 3 的除数。注意:我目前没有参加比赛。
-
我忘了说时间限制是1秒
-
@Ali - 我做了一些编辑,看看我所做的更改。另外,请编辑您的问题并添加您作为 cmets 添加的详细信息(1 秒限制,您尝试过的内容)