题目:求和问题
描述:
【问题描述】
在一个长度为n的整数数列中取出连续的若干个数,并求它们的和。
【输入格式】
输入由若干行组成,第一行有一个整数n
第二行有n个整数
第三行有一个整数m
下面m行,每行两个整数i与j(i<=j),表示求和的起始和终止位置。
第二行有n个整数
第三行有一个整数m
下面m行,每行两个整数i与j(i<=j),表示求和的起始和终止位置。
【输出格式】
输出有m行, 每行一个整数,表示这个数段数列的和。
【输入样例】
输入文件
8
2 3 4 7 8 9 10 234
5
2 3
4 7
1 3
7 7
7 8
2 3 4 7 8 9 10 234
5
2 3
4 7
1 3
7 7
7 8
输出文件
7
34
9
10
244
34
9
10
244
【数据规模】
对于40%的数据,n<=1000,m<=1000,数列中的数不超过32767,数列的和不超过10^9
对于70%的数据,n<=10000,m<=2*10^5,数列中的数不超过32767
对于100%的数据,n<=10000,m<=2*10^5,数列中的数不超过10^9
对于70%的数据,n<=10000,m<=2*10^5,数列中的数不超过32767
对于100%的数据,n<=10000,m<=2*10^5,数列中的数不超过10^9
果的树状数组,直接处理,查找1~i-1的值和1~j的值,相减即为答案。但数据大小较坑,但int64轻松解决。评论中说有一组数据还有0 0的奇葩情况……于是很多人被坑……感谢评论,直接特判……还有就是,以后一定要注意读入的方式,因为写成了换行读入,结果WA了一次,以后一定要注意。
AC代码:
{
program zht; var n,i,j,t,x,y,m:longint; q,w:int64; a,c:array[0..20000] of int64; begin assign(input,'sum.in'); assign(output,'sum.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do read(a[i]); for i:=1 to n do begin t:=i and (-i); for j:=i-t+1 to i do c[i]:=c[i]+a[j]; end; // jian shu t:=0; readln(m); for i:=1 to m do begin readln(x,y); if x+y=0 then begin writeln('0'); continue; end; q:=0; w:=0; t:=x-1; while t>0 do begin q:=q+c[t]; t:=t-(t and (-t)); end; t:=y; while t>0 do begin w:=w+c[t]; t:=t-(t and (-t)); end; writeln(w-q); end; close(input); close(output); end.
}
<Marvolo原创,严禁转载>