poj 3468 A Simple Problem with Integers(线段树)(第二部分 成段更新,区间求和)

来源:互联网 发布:山东省网络快报系统 编辑:程序博客网 时间:2024/05/02 05:03

题目链接:http://poj.org/problem?id=3468

题目大意:给出n个数的数值

Q是对区间a,b的求和

C是对区间a,b内的所有数都加上c

思路:成段更新,需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候

#include<iostream>#include<cmath>#include<cstdio>#include<iomanip>#include<cstring>#include<stdlib.h>#include<string>#include<algorithm>#include<queue>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int  maxn =110000;#define LL long longLL sum[maxn<<2];LL add[maxn<<2];void pushup(int rt)//将当前结点的信息更新的父节点{sum[rt]=sum[rt<<1]+sum[rt<<1|1];//sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);}void pushdown(int rt,LL m)//延迟标记向下推 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 ;}LL m=(l+r)>>1;build(lson);build(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);LL m=(l+r)>>1;LL ret=0;if(L<=m)ret+=query(L,R,lson);if(R>m)ret=ret+query(L,R,rson);return ret;}void update(int L,int R,int a,int l,int r,int rt){if(L<=l&&r<=R){add[rt]+=a;sum[rt]+=(LL)a*(r-l+1);return ;}pushdown(rt,r-l+1);LL m=(l+r)>>1;if(L<=m)update(L,R,a,lson);if(R>m) update(L,R,a,rson);pushup(rt);//子节点更新完之后也要对其父节点不断往上的更新}int main(){int n,m;while(~scanf("%d%d",&n,&m)){build(1,n,1);char op[10];while(m--){scanf("%s",op);int a,b,c;scanf("%d%d",&a,&b);if(op[0]=='Q')//访问{printf("%lld\n",query(a,b,1,n,1));}else if(op[0]=='C'){scanf("%d",&c);update(a,b,c,1,n,1);}}}return 0;}


阅读全文
0 0