【模板】线段树 1
题目描述
如题,已知一个数列,你需要进行下面两种操作:
- 将某区间每一个数加上 k k k。
- 求出某区间每一个数的和。
输入格式
第一行包含两个整数 n , m n, m n,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。
接下来 m m m 行每行包含 3 3 3 或 4 4 4 个整数,表示一个操作,具体如下:
1 x y k
:将区间 [ x , y ] [x, y] [x,y] 内每个数加上 k k k。2 x y
:输出区间 [ x , y ] [x, y] [x,y] 内每个数的和。
输出格式
输出包含若干行整数,即为所有操作 2 的结果。
样例 #1
样例输入 #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
提示
对于
30
%
30\%
30% 的数据:
n
≤
8
n \le 8
n≤8,
m
≤
10
m \le 10
m≤10。
对于
70
%
70\%
70% 的数据:
n
≤
10
3
n \le {10}^3
n≤103,
m
≤
10
4
m \le {10}^4
m≤104。
对于
100
%
100\%
100% 的数据:
1
≤
n
,
m
≤
10
5
1 \le n, m \le {10}^5
1≤n,m≤105。
保证任意时刻数列中所有元素的绝对值之和 ≤ 10 18 \le {10}^{18} ≤1018。
【样例解释】
#include<bits/stdc++.h>
using namespace std;
unsigned long long n,m,a[1000001],ans[1000001<<2],tag[1000001<<2];
inline long long ls(long long x)
{
return x<<1;
}
inline long long rs(long long x)
{
return x<<1|1;
}
void scan()
{
cin>>n>>m;
for(long long i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
}
inline void push_up(long long p)
{
ans[p]=ans[ls(p)]+ans[rs(p)];
}
void build(long long p,long long l,long long r)
{
tag[p]=0;
if(l==r)
{
ans[p]=a[l];return ;
}
long long mid=(l+r)>>1;
build(ls(p),l,mid);
build(rs(p),mid+1,r);
push_up(p);
}
inline void f(long long p,long long l,long long r,long long k)
{
tag[p]=tag[p]+k;
ans[p]=ans[p]+k*(r-l+1);
}
inline void push_down(long long p,long long l,long long r)
{
long long mid=(l+r)>>1;
f(ls(p),l,mid,tag[p]);
f(rs(p),mid+1,r,tag[p]);
tag[p]=0;
}
inline void update(long long nl,long long nr,long long l,long long r,long long p,long long k)
{
if(nl<=l&&r<=nr)
{
ans[p]+=k*(r-l+1);
tag[p]+=k;
return ;
}
push_down(p,l,r);
long long mid=(l+r)>>1;
if(nl<=mid)
{
update(nl,nr,l,mid,ls(p),k);
}
if(nr>mid)
{
update(nl,nr,mid+1,r,rs(p),k);
}
push_up(p);
}
long long query(long long q_x,long long q_y,long long l,long long r,long long p)
{
long long res=0;
if(q_x<=l&&r<=q_y)
{
return ans[p];
}
long long mid=(l+r)>>1;
push_down(p,l,r);
if(q_x<=mid)
{
res+=query(q_x,q_y,l,mid,ls(p));
}
if(q_y>mid)
{
res+=query(q_x,q_y,mid+1,r,rs(p));
}
return res;
}
int main()
{
long long a1,b,c,d,e,f;
scan();
build(1,1,n);
while(m--)
{
scanf("%lld",&a1);
switch(a1)
{
case 1:
{
scanf("%lld%lld%lld",&b,&c,&d);
update(b,c,1,n,1,d);
break;
}
case 2:
{
scanf("%lld%lld",&e,&f);
printf("%lld\n",query(e,f,1,n,1));
break;
}
}
}
return 0;
}