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;
}
posted @ 2011-04-08 16:48  L..  阅读(318)  评论(0编辑  收藏  举报