题目:gg查成绩
题目描述
这一天gg拿到了一份,超多的考试数据a 。 老师要求他按照询问数据告诉老师,第几个到第几个同学的分数和是多少 ?
gg最近入职字节跳动了,没有时间处理这种极其简单的问题,所以请你顺手秒一下。
输入描述
bash 第一行n m ( n个同学 m次询问)
1 <= n <= 106
1 <= m <= 104
第二行输入n个整数表示成绩
a1 a2…an (0 <= ai<= 100) 1<=i<=n
以下m行为两个整数 bi bj 表示第几个到第几个同学(从1开始)
1<=bi<=bj<=n
输出描述
m行查询结果
示例1
输入
10 3
11 22 33 44 55 66 77 88 99 10
1 4
2 10
5 7
输出
110
494
198
说明:
注意第几个是按照输入顺序 不要排序 不要排序 不要排序
思路
一、 如果按照常规方法解决的话:
- 开设一个1000000的int数组
- 输入n,m
- 输入n个数存入数组
- 输出m组bi bj
- 用循环实现加法
但是这样的时间复杂度就可能会非常大(1000000不是一个很小的数字,最大为O(n*(m+1))
二、 如果用另一种方法:
- 开设一个1000000的int数组(用来存放前 i 项和)
- 输入n,m
- 输入n 个数,并加上数组中前一项存入数组
- 输入 m 组bi bj
- 求和直接用
第 bj 项 - 第(bi-1)项
这样的时间复杂度就会大约为O(n);
总结
在做题时,尽可能将时间复杂度降低
以下为代码:
(一)
//未能通过(通过71.43% 运行超时)
#include<stdio.h>
int c[1000001]; //在我的编译器上main函数里不能直接开这么大的数组,但是作为全局变量就可以
int main()
{
int n,m;
scanf("%d %d",&n,&m);
//int c[1000001];
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&c[i]);
}
while(m)
{
int bi,bj;
int s=0;
scanf("%d %d",&bi,&bj);
for(;bi<=bj;bi++)
{
s+=c[bi];
}
printf("%d\n",s);
s=0;
m--;
}
}
(二)
#include<stdio.h>
int c[1000001];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
//int c[1000001];
int i;
c[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&c[i]);
c[i]+=c[i-1];
}
while(m)
{
int bi,bj;
scanf("%d %d",&bi,&bj);
printf("%d\n",c[bj]-c[bi-1]);
m--;
}
}
题目来源:https://ac.nowcoder.com/acm/contest/11471/C