标签:
http://poj.org/problem?id=3468
_(:зゝ∠)_我又活着回来啦,前段时间太忙了写的题没时间扔上来,以后再说。
【问题描述】
成段加某一个值,然后询问区间和。
【思路】
讲一下pushdown和pushup出现的几个位置。
pushup:
(1)build的结尾,当叶子节点分别有对应的值后,它的父亲们就等于它们求和。
(2)update的结尾,因为此时当前根的左右孩子已经更新了,故它也需要更新。
pushdown(延迟标记):
*pushdown会出现在一切要从当前结点往下的位置
query和update中,要先把add的值传给两个儿子。
接下来整理一下思路,每一个子过程分别需要如何操作:
build(建立线段树)
(1)将add清零
(2)如果左子树等于右子树,则说明已经到达叶子节点,读入sum的值,返回
(3)向左右子树递归
(4)pushup更新当前根
update(修改)
(1)如果当前的L和R包含在l和r中,则让add+δ,让sum+δ*当前区间的长度,返回
(2)pushdown向下延迟标记
(3)向左右子树递归
(4)pushup更新当前根
query(查询)
(1)如果当前的L和R包含在l和r中,则直接返回sum[rt]
(2)pushdown向下延迟标记
(3)向左右子树递归,将得到的返回值加到result总
(4)返回result
一般的线段树就是这样操作的,其实还挺简单(??∀?)??最近学业有点忙好久没写程序了,整理一个当作恢复一下手速。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 #define lson l,m,rt<<1 8 #define rson m+1,r,rt<<1|1 9 #define LL long long 10 const int MAXN=400000+500; 11 int n,q; 12 LL add[MAXN]; 13 LL sum[MAXN]; 14 15 void pushup(int rt) 16 { 17 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 18 } 19 20 void build(int l,int r,int rt) 21 { 22 add[rt]=0; 23 if (l==r) 24 { 25 scanf("%lld",&sum[rt]); 26 return; 27 } 28 int m=(l+r)/2; 29 build(lson); 30 build(rson); 31 pushup(rt); 32 } 33 34 void pushdown(int rt,int m) 35 { 36 if (add[rt]) 37 { 38 add[rt<<1]+=add[rt]; 39 add[rt<<1|1]+=add[rt]; 40 sum[rt<<1]+=add[rt]*(m-(m>>1)); 41 sum[rt<<1|1]+=add[rt]*(m>>1); 42 add[rt]=0; 43 } 44 } 45 46 LL query(int L,int R,int l,int r,int rt) 47 { 48 if (L<=l && R>=r) 49 { 50 return sum[rt]; 51 } 52 pushdown(rt,r-l+1); 53 int m=(l+r)/2; 54 LL rs=0; 55 if (m>=L) rs+=query(L,R,lson); 56 if (m<R) rs+=query(L,R,rson); 57 return rs; 58 } 59 60 void update(int L,int R,int delta,int l,int r,int rt) 61 { 62 if (L<=l && R>=r) 63 { 64 add[rt]+=delta; 65 sum[rt]+=(LL)delta*(r-l+1); 66 return; 67 } 68 pushdown(rt,r-l+1); 69 int m=(l+r)/2; 70 if (m>=L) update(L,R,delta,lson); 71 if (m<R) update(L,R,delta,rson); 72 pushup(rt); 73 } 74 75 int main() 76 { 77 scanf("%d%d",&n,&q); 78 build(1,n,1); 79 for (int i=0;i<q;i++) 80 { 81 char c[2]; 82 scanf("%s",c); 83 if (c[0]==‘C‘) 84 { 85 int fr,ed,ad; 86 scanf("%d%d%d",&fr,&ed,&ad); 87 update(fr,ed,ad,1,n,1); 88 } 89 else 90 { 91 int a,b; 92 scanf("%d%d",&a,&b); 93 cout<<query(a,b,1,n,1)<<endl; 94 } 95 } 96 return 0; 97 }
【成端更新线段树模板】POJ3468-A Simple Problem with Integers
标签:
原文地址:http://www.cnblogs.com/iiyiyi/p/5001895.html