POJ 3468 A Simple Problem with Integers

给你一段数列 两个操作
"C  a  b  c" means adding  c to each of  AaAa +1, ... ,  Ab. -10000 ≤  c ≤ 10000. 一段区间同时增加一个值
"Q  a  b" means querying the sum of  AaAa +1, ... ,  Ab.查询一段区间的值
这题很好的体现了lazy_tag的思想,当要增加的区间覆盖当前区间,则直接打上标记返回,当下次查询这个区间儿子区间的时候,直接标记往下传。
可以想象,这个标记表示的是这个区间表示的整个区间的标记,是整个子树的性质,当你不需要用到这个区间的儿子区间的时候,你可以不把操作
都做到底,而是要用到的时候再往下传!详见代码
   
     
#include < stdio.h >
#include
< stdlib.h >
#define L(t) ((t) << 1)
#define R(t) ((t) << 1 | 1)
#define ll long long
#define MAXN 100000
struct SegTree{
int l,r;
ll add, sum;
int getMid(){
return ( l + r) >> 1 ;
}
int getDis(){
return r - l + 1 ;
}
}tree[MAXN
<< 2 ];
int val[ 100010 ];

void bulid( int left, int right, int t){
tree[t].l
= left;
tree[t].r
= right;
tree[t].add
= 0 ;
if (left == right){
tree[t].sum
= val[left];
return ;
}
int mid = tree[t].getMid();
bulid(left, mid, L(t));
bulid(mid
+ 1 , right, R(t));
tree[t].sum
= tree[L(t)].sum + tree[R(t)].sum;
}
void update( int left, int right, int a, int t){
if ( left <= tree[t].l && right >= tree[t].r ){
tree[t].add
+= a; // 覆盖这个区间 add增加 同时更新sum 这时add表示子树要增加的增量
tree[t].sum += a * tree[t].getDis();
return ;
}
if ( tree[t].add ){ // 如果增量不为空,向下传递,同时更新儿子的sum值,最后清空自己的增量
tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;
tree[R(t)].sum
+= tree[R(t)].getDis() * tree[t].add;
tree[L(t)].add
+= tree[t].add;
tree[R(t)].add
+= tree[t].add;
tree[t].add
= 0 ;
}
int mid = tree[t].getMid();
if (right <= mid ){
update(left, right, a, L(t));
}
else if (left > mid ){
update(left, right, a, R(t));
}
else {
update(left, mid, a, L(t));
update(mid
+ 1 , right, a, R(t));
}
tree[t].sum
= tree[L(t)].sum + tree[R(t)].sum ; // 递归回来后 由左右孩子的sum值更新父亲的sum值
}
ll query(
int left, int right, int t){
if (left <= tree[t].l && right >= tree[t].r ){
return tree[t].sum;
}
if ( tree[t].add ){ // 同理
tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;
tree[R(t)].sum
+= tree[R(t)].getDis() * tree[t].add;
tree[L(t)].add
+= tree[t].add;
tree[R(t)].add
+= tree[t].add;
tree[t].add
= 0 ;
}
int mid = tree[t].getMid();
if (right <= mid ){
return query(left, right, L(t));
}
else if ( left > mid ){
return query(left, right, R(t));
}
else {
return query(left, mid ,L(t)) +
query(mid
+ 1 , right, R(t));
}
}
int main(){
char cmd[ 3 ];
int n, q;
scanf(
" %d%d " , & n, & q);
for ( int i = 1 ; i <= n; ++ i){
scanf(
" %d " , & val[i]);
}
bulid(
1 , n, 1 ); // 不要每次都忘掉 !
for ( int i = 1 ; i <= q; ++ i){
scanf(
" %s " ,cmd);
if (cmd[ 0 ] == ' Q ' ){
int a, b;
scanf(
" %d %d " , & a, & b);
ll ans
= query(a, b, 1 );
printf(
" %lld\n " ,ans);
}
else {
int a, b, c;
scanf(
" %d%d%d " , & a, & b, & c);
update(a, b, c,
1 );
}
}
return 0 ;
}

你可能感兴趣的:(Integer)