题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2x y 含义:输出区间[x,y]内每个数的和
输出格式:
输出包含若干行整数,即为所有操作2的结果。
输入样例#1:
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1:
11
8
20
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
解题思路:这道题目可用树状数组或线段树来解决。以下提供两种算法的代码(模板)
代码:(请不要直接拷贝哦)
//(树状数组) Var n,m,k,l,r,u,j,s1,s2:int64; i:longint; a,c,d:array[0..500000]of int64; function lowbit(x:int64):int64; begin exit(x and (-x)); end; procedure add1(x,y:int64); begin while x<=n do begin inc(c[x],y); x:=x+lowbit(x); end; end; procedure add2(x,y:int64); begin while x<=n do begin inc(d[x],y); x:=x+lowbit(x); end; end; function sum1(x:int64):int64; var t:int64; begin t:=0; while x>0 do begin inc(t,c[x]); dec(x,lowbit(x)); end; exit(t); end; function sum2(x:int64):int64; var t:int64; begin t:=0; while x>0 do begin inc(t,d[x]); dec(x,lowbit(x)); end; exit(t); end; begin readln(n,m); for i:=1 to n do read(a[i]); for i:=1 to n do begin add1(i,a[i]-a[i-1]); add2(i,(i-1)*(a[i]-a[i-1])); end; for i:=1 to m do begin read(u); if u=1 then begin readln(l,r,k); add1(l,k); add1(r+1,-k); add2(l,(l-1)*k); add2(r+1,r*(-k)); end else begin readln(l,r); s1:=(l-1)*sum1(l-1)-sum2(l-1); s2:=r*sum1(r)-sum2(r); writeln(s2-s1); end; end; end.
//线段树 #include <cstdio> #define ll long long using namespace std; struct TREE{ ll l,r,sum,lazy; }tree[400005]; ll n,m,b,c,d,a[100005]; inline int read() { ll f=1,x=0; char ch=getchar(); if (ch=='-') { f=-1; ch=getchar(); } while ((ch<'0')||(ch>'9')) ch=getchar(); while ((ch>='0')&&(ch<='9')) { x=x*10+ch-48; ch=getchar(); } return f*x; } inline void build(ll root,ll l,ll r) { tree[root].l=l; tree[root].r=r; if (l==r) { tree[root].sum=a[l]; return; } ll mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); tree[root].sum=tree[root*2].sum+tree[root*2+1].sum; } inline void js(ll root,ll l,ll r,ll d) { tree[root].lazy+=d; tree[root].sum+=d*(r-l+1); } inline void push_down(ll root,ll l,ll r) { ll mid=(l+r)/2; js(root*2,l,mid,tree[root].lazy); js(root*2+1,mid+1,r,tree[root].lazy); tree[root].lazy=0; } inline void change(ll root,ll l,ll r) { int nl=tree[root].l,nr=tree[root].r; int mid=(nl+nr)/2; if ((l<=nl)&&(nr<=r)) { tree[root].sum+=d*(nr-nl+1); tree[root].lazy+=d; return; } push_down(root,nl,nr); if (l<=mid) change(root*2,l,r); if (r>mid) change(root*2+1,l,r); tree[root].sum=tree[root*2].sum+tree[root*2+1].sum; } inline ll find(ll root,ll l,ll r) { ll s=0,nl=tree[root].l,nr=tree[root].r; if ((l<=nl)&&(nr<=r)) return tree[root].sum; ll mid=(nl+nr)/2; push_down(root,nl,nr); if (l<=mid) s+=find(root*2,l,r); if (r>mid) s+=find(root*2+1,l,r); return s; } int main() { n=read(),m=read(); for (ll i=1;i<=n;i++) a[i]=read(); build(1,1,n); for (ll i=1;i<=m;i++) { ll x; x=read(); if (x==1) { b=read(),c=read(),d=read(); change(1,b,c); } else { b=read(),c=read(); printf("%lld\n",find(1,b,c)); } } return 0; }