时间限制:1.2 s 内存限制:128 MB
【问题描述】
在一个长度为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
线段树区间求和
#include <cstdio> using namespace std; typedef long long LL; struct node { LL l,r,dis; }tree[1000001]; LL ans,u,v,m,n,i,j; void up(LL now) { tree[now].dis=tree[now*2].dis+tree[now*2+1].dis; } void read(LL &x) { x=0;LL f=1; char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+(LL)ch-48;ch=getchar();} x=x*f; } void build(LL l,LL r,LL now) { tree[now].l=l;tree[now].r=r; if(tree[now].l==tree[now].r) { read(tree[now].dis); return; } LL mid=(l+r)>>1; build(l,mid,now*2); build(mid+1,r,now*2+1); up(now); } void query(LL now) { if(tree[now].l>=u&&tree[now].r<=v) { ans+=tree[now].dis; return; } LL m=(tree[now].l+tree[now].r)>>1; if(u<=m) query(now<<1); if(v>m) query(now<<1|1); } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); read(n); build(1,n,1); read(m); while(m--) { read(u);read(v); ans=0;query(1); printf("%lld ",ans); } fclose(stdin); fclose(stdout); return 0; }