题意:你有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; }
POJ A Simple Problem with Integers 【线段树,区间更新】,布布扣,bubuko.com
POJ A Simple Problem with Integers 【线段树,区间更新】
原文地址:http://blog.csdn.net/shengweisong/article/details/38413603