poj3468---线段树----区间单点更新、区间和查询----有延迟标记

指定区间,对区间里的每个数进行统一的操作(加和),这里用到延迟数组标记。


树状数组线段树建树,每个节点表示该节点所在区间的和。


add [ ]数组用来标记当前节点所延迟的向下加和的数。


PushDown() 向下更新。

#include<stdio.h>
#define maxn 110000 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define LL long long int n, cas; LL add[maxn<<2]; LL sum[maxn<<2]; LL operate(LL a, LL b){ return a+b; } void PushUp(int rt){ sum[rt] = operate(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 build(int l, int r, int rt){ add[rt] = 0; if(l == r){ scanf("%lld", &sum[rt]); return; } int m = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void Update(int L, int R, int c, int l, int r, int rt){ if(L<=l && r<=R){ add[rt] += c; sum[rt] += (LL)c * (r-l+1); return ; } PushDown(rt, r-l+1); int m = (l+r)>>1; if(L<=m) Update(L, R, c, lson); if(R>m) Update(L, R, c, rson); PushUp(rt); } LL Query(int L, int R, int l, int r, int rt){ if(L<=l && r<=R){ return sum[rt]; } PushDown(rt, r-l+1); int m = (l+r)>>1; LL ret = 0; if(L<=m) ret += Query(L, R, lson); if(R>m) ret += Query(L, R, rson); return ret; } int main(){ int a, b, c; char ch[2]; //freopen("in.txt", "r", stdin); while(scanf("%d %d", &n, &cas) != EOF){ build(1, n, 1); while(cas--){ scanf("%s", ch); if(ch[0] == 'Q'){ scanf("%d %d", &a, &b); printf("%lld\n", Query(a, b, 1, n, 1)); }else if(ch[0] == 'C'){ scanf("%d %d %d", &a, &b, &c); Update(a, b, c, 1, n, 1); } } } return 0; }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值