题目连接:http://poj.org/problem?id=3468
线段树功能:update:成段增减 query:区间求和。
分析:需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long #define M 1000000000 #define maxn 111111 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; LL sum[maxn<<2]; LL col[maxn<<2]; void Pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Pushdown(int rt,int m) { if(col[rt]) { col[rt<<1]+=col[rt]; col[rt<<1|1]+=col[rt]; sum[rt<<1]+=col[rt]*(m-(m>>1)); sum[rt<<1|1]+=col[rt]*(m>>1); col[rt]=0; } } void build(int l,int r,int rt) { col[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) { col[rt]+=c; sum[rt]+=(LL)(r-l+1)*c; return; } Pushdown(rt,r-l+1); int m=(l+r)>>1; if(L<=m)update(L,R,c,lson); if(m<R)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=(r+l)>>1; LL res=0; if(L<=m)res+=query(L,R,lson); if(R>m)res+=query(L,R,rson); return res; } int main() { int n,m; char op[10]; while(scanf("%d%d",&n,&m)>0) { build(1,n,1); while(m--) { int a,b,c; scanf("%s",op); if(op[0]=='Q') { scanf("%d%d",&a,&b); printf("%lld\n",query(a,b,1,n,1)); } else { scanf("%d%d%d",&a,&b,&c); update(a,b,c,1,n,1); } } } return 0; }