POJ 3468 A Simple Problem with Integers 【线段树,区间更新】
题意:你有N个整数,A1,A2,…,一个。你须要处理两种类型的操作。一种类型的操作是加入了一些给定的数字,每一个数字在一个给定的时间间隔。
还有一种是在给定的时间间隔要求数量的总和。
难点:主要是lazy标记,不好弄懂, 事实上lazy标记就是当前改变的值不所有更新。等到用的时候再更新,这样就节省了好多时间。
题目链接:http://poj.org/problem?id=3468
代码:
#include<stdio.h> #include<string.h> #define MAXN 100005 #define LC l, m, rt<<1 #define RC m+1, r, rt<<1|1 #define LL __int64 LL sum[MAXN<<2], add[MAXN<<2];//add数组就是临时储存要添加的 void pushup(int rt) { sum[rt] = sum[rt<<1]+sum[rt<<1|1]; } void pushdown(int rt, int m)//这个是难点。理解了这个这道题就差点儿相同了 { if(add[rt]){ add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt]*(m-(m>>1)); sum[rt<<1|1] += add[rt]*(m>>1); add[rt] = 0; } } void creat(int l,int r,int rt) { add[rt] = 0; if (l == r) { scanf("%I64d",&sum[rt]); return ; } int m = (l + r) >> 1; creat(LC); creat(RC); pushup(rt); } void update(int le, int ri, int num, int l, int r, int rt) { if(le <= l&&r<=ri){ add[rt] += num; sum[rt] += (LL)num*(r-l+1); return; } pushdown(rt, r-l+1); int m = (l+r)>>1; if(le <=m) update(le, ri, num, LC); if(ri > m) update(le, ri, num, RC); pushup(rt); } LL query(int le, int ri, int l, int r, int rt) { if(le <= l&&r<=ri){ return sum[rt]; } pushdown(rt, r-l+1); LL res = 0; LL m = (l+r)>>1; if(le <= m) res += query(le, ri, LC); if(ri > m) res += query(le, ri, RC); return res; } int main() { int n, m; scanf("%d%d", &n, &m); creat(1, n, 1); char s[2]; int a, b, c; while(m --){ scanf("%s", s); if(s[0] == 'Q'){ scanf("%d%d", &a, &b); printf("%I64d\n", query(a, b, 1, n, 1)); } else{ scanf("%d%d%d", &a, &b, &c); update(a, b, c, 1, n, 1); } } return 0; }
posted on 2017-04-17 14:03 gavanwanggw 阅读(128) 评论(0) 编辑 收藏 举报