原题地址POJ - 3468
队长给出了一个序列,想让你帮队长干活,你需要处理如下两种情况。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
Input
第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。
接下来Q行询问,格式如题目描述。
Output
对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。
Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output
4
55
9
15
直接建树就完了,版子题。
下放:
void
pushdown
(
int
rt
) {
// pushdown
操作
if
(
tre
[
rt
].
lazy
) {
tre
[
rt
*
2
].
lazy
+=
tre
[
rt
].
lazy
;
//
把父节点
rt
的
lazy
传给左右儿子
tre
[
rt
*
2
+
1
].
lazy
+=
tre
[
rt
].
lazy
;
tre
[
rt
*
2
].
sum
+=
(
tre
[
rt
*
2
].
r
-
tre
[
rt
*
2
].
l
+
1
)
*
tre
[
rt
].
lazy
;
// sum
加 上的值就是区 间长度*
父节点
.lazy
tre
[
rt
*
2
+
1
].
sum
+=
(
tre
[
rt
*
2
+
1
].
r
-
tre
[
rt
*
2
+
1
].
l
+
1
)
*
tre
[
rt
].
lazy
;
tre
[
rt
].
lazy
=
0
;
//
不要忘记清空
lazy
}
}
核心建树:
关键查询:
修改:
void
modify
(
int
rt
,
int
l
,
int
r
,
ll pos
) {
if
(
tre
[
rt
].
l
>=
l
&&
tre
[
rt
].
r
<=
r
) {
tre
[
rt
].
sum
+=
(
tre
[
rt
].
r
-
tre
[
rt
].
l
+
1
)
*
pos
;
// 如果有完整区间,给这个区间加上lazy
标记,下面的路先不需要走
tre
[
rt
].
lazy
+=
pos
;
//
给
lazy += pos
,表示
lazy
是需要给以
rt
为根的所有子树加pos
}
else
{
pushdown
(
rt
);
//
没有找到完整区间就一直
pushdown
int
mid
=
tre
[
rt
].
mid
();
if
(
l
<=
mid
)
modify
(
rt
*
2
,
l
,
r
,
pos
);
if
(
r
>
mid
)
modify
(
rt
*
2
+
1
,
l
,
r
,
pos
);
pushup
(
rt
);
//
这里记得需要
pushup
,利用回溯过程,更新父节点信息
}
}
完整代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<stdio.h>
using namespace std;
const int N=100005;
int a[N];
struct node{
int l,r;
long long sum;//注意范围
long long lazy;
int mid(){
return (l+r)/2;
}
}tree[N*4];
void pushup(int rt){
tree[rt].sum=tree[rt*2].sum+tree[rt*2+1].sum;
}
void pushdown(int rt){
if(tree[rt].lazy){
tree[rt*2].lazy+=tree[rt].lazy;
tree[rt*2+1].lazy+=tree[rt].lazy;
tree[rt*2].sum+=(tree[rt*2].r-tree[rt*2].l+1)*tree[rt].lazy;
tree[rt*2+1].sum+=(tree[rt*2+1].r-tree[rt*2+1].l+1)*tree[rt].lazy;
tree[rt].lazy=0;
}
}
void build(int rt,int l,int r){
if(l==r) tree[rt]={l,r,a[l],0};
else {
tree[rt]={l,r};
int mid=tree[rt].mid();
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
pushup(rt);
}
}
long long query(int rt,int l,int r){
if(tree[rt].l>=l&&tree[rt].r<=r){
return tree[rt].sum;
}
else {
pushdown(rt);
int mid=tree[rt].mid();
long long sum=0;
if(l<=mid) sum+=query(rt*2,l,r);
if(r>mid) sum+=query(rt*2+1,l,r);
return sum;
}
}
void modify(int rt,int l,int r,long long pos){
if(tree[rt].l>=l&&tree[rt].r<=r){
tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*pos;
tree[rt].lazy+=pos;
}
else{
pushdown(rt);
int mid=tree[rt].mid();
if(l<=mid) modify(rt*2,l,r,pos);
if(r>mid) modify(rt*2+1,l,r,pos);
pushup(rt);
}
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
while(m--){
char op[5];
cin>>op;
int l,r;
cin>>l>>r;
long long pos;
if(op[0]=='Q') {
long long opp=query(1,l,r);
cout<<opp<<"\n";
}
else {
cin>>pos;
modify(1,l,r,pos);
}
}
}