標籤:線段樹 區間更新
題意:你有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 __int64LL 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;}