【模板】线段树 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。
【样例解释】
题目分析
简单地套用线段树模板,注意数据范围要用长整型
AC Code
#include<bits/stdc++.h>
using namespace std;
#define FOR(i,start,end) for(int i=start;i<=end;i++)
#define ROF(i,start,end) for(int i=start;i>=end;i--)
#define EPS 1e-8
#define INF 0x3f3f3f3f
#define mm0(x) memset(x,0,sizeof(x))
#define mm_1(x) memset(x,-1,sizeof(x))
#define mm3f(x) memset(x,0x3f,sizeof(x))
#define db1(a) cout<<#a<<"="<<a<<endl
#define db2(a,i) cout<<#a<<"["<<i<<"]="<<endl
#define db3(a,i,j) cout<<#a<<"["<<i<<"]["<<j<<"]="<<a[i][j]<<endl
typedef long long ll;
typedef pair<int,int> pii;
// begin code
const int N=100005;
struct node {
int ls,rs;
ll sum,lazy;
} tr[N<<2];
ll a[N];
void pushup(int u) {
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void build(int u,int l,int r) {
tr[u].lazy=0;
tr[u].ls=l;
tr[u].rs=r;
if(l==r) {
tr[u].sum=a[l];
return;
}
int m=l+((r-l)>>1);
build(u<<1,l,m);
build(u<<1|1,m+1,r);
pushup(u);
}
void pushdown(int u) {
if(tr[u].lazy) {
tr[u<<1].sum+=tr[u].lazy*(tr[u<<1].rs-tr[u<<1].ls+1);
tr[u<<1|1].sum+=tr[u].lazy*(tr[u<<1|1].rs-tr[u<<1|1].ls+1);
tr[u<<1].lazy+=tr[u].lazy;
tr[u<<1|1].lazy+=tr[u].lazy;
tr[u].lazy=0;
}
}
void update(int u,int l,int r,int st,int en,ll k) {
if(st<=l&&r<=en) {
tr[u].sum+=k*(tr[u].rs-tr[u].ls+1);
tr[u].lazy+=k;
return;
}
if(l!=r)pushdown(u);
int m=l+((r-l)>>1);
if(st<=m)update(u<<1,l,m,st,en,k);
if(en>m)update(u<<1|1,m+1,r,st,en,k);
pushup(u);
}
ll query(int u,int l,int r,int st,int en) {
if(st<=l&&r<=en) {
return tr[u].sum;
}
if(l!=r)pushdown(u);
ll sum=0;
int m=l+((r-l)>>1);
if(st<=m)sum+=query(u<<1,l,m,st,en);
if(en>m)sum+=query(u<<1|1,m+1,r,st,en);
return sum;
}
// end code
//#define DEBUG
int main() {
//提高cin,cout的速度
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#ifdef DEBUG
freopen("P3372.in","r",stdin);
// freopen("P3372.ans","w",stdout);
#endif
// begin main code
int n,m;
cin>>n>>m;
FOR(i,1,n)cin>>a[i];
build(1,1,n);
int op,x,y,k;
while(m--){
cin>>op;
if(op==1) {
cin>>x>>y>>k;
update(1,1,n,x,y,k);
} else {
cin>>x>>y;
cout<<query(1,1,n,x,y)<<endl;
}
}
// end code
#ifdef DEBUG
fclose(stdin);
// fclose(stdout);
#endif
return 0;
}
,y,k);
} else {
cin>>x>>y;
cout<<query(1,1,n,x,y)<<endl;
}
}
// end code
#ifdef DEBUG
fclose(stdin);
// fclose(stdout);
#endif
return 0;
}