Poj 3468--线段树
http://poj.org/problem?id=3468
线段树成段更新模版题。。但是这里这个惰性标记有点神奇,,看了好久才理解。。
这里简单的讲下懒惰标记,懒惰标记即是要修改一个区间的时候,暂时不需要修改区间中的每个点,加一个标志代表这个区间被修改了,等到需要查询一个小区间的时候再具体修改。至于为什么要这样呢,不妨这么考虑,当更新一段区间的时候,如果没有懒惰标记,一开始如果找到的区间比要更新的区间大,那么这个大的区间里的每个点都需要修改,这样时间复杂度就是o(n)了,这跟没用线段树一样,至于单点更新为什么不需要这个呢,是因为单点更新都是更新一个点,所以不会出现更新区间这样的问题,而采用了懒惰标记,只是对当前父亲节点进行标记,当找到更新的区间时,才会进行更新,而不是在每次找区间的时候都更新,这样的时间复杂度才是线段树的复杂度。
代码:
View Code
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define maxn 100100 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 long long sum[maxn<<2],flag[maxn<<2]; 8 void Pushup(int rt) 9 { 10 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 11 } 12 void Pushdown(int rt,int num) 13 { 14 flag[rt<<1]+=flag[rt]; 15 flag[rt<<1|1]+=flag[rt]; 16 sum[rt<<1]+=(num-(num>>1))*flag[rt]; 17 sum[rt<<1|1]+=(num>>1)*flag[rt]; 18 flag[rt]=0; 19 } 20 void build(int l,int r,int rt) 21 { 22 flag[rt]=0; 23 if(l==r) 24 { 25 scanf("%lld",&sum[rt]); 26 return ; 27 } 28 int m=(l+r)>>1; 29 build(lson); 30 build(rson); 31 Pushup(rt); 32 } 33 void update(int L,int R,int w,int l,int r,int rt) 34 { 35 if(L<=l&&r<=R) 36 { 37 flag[rt]+=w; 38 sum[rt]+=(long long)(r-l+1)*w; 39 return; 40 } 41 Pushdown(rt,r-l+1); 42 int m=(l+r)>>1; 43 if(L<=m) update(L,R,w,lson); 44 if(R>m) update(L,R,w,rson); 45 Pushup(rt); 46 } 47 long long query(int L,int R,int l,int r,int rt) 48 { 49 if(L<=l&&r<=R) 50 return sum[rt]; 51 Pushdown(rt,r-l+1); 52 long long ret=0; 53 int m=(l+r)>>1; 54 if(L<=m) ret+=query(L,R,lson); 55 if(R>m) ret+=query(L,R,rson); 56 return ret; 57 } 58 int main() 59 { 60 int n,m,a,b,w; 61 char c[2]; 62 while(~scanf("%d %d",&n,&m)) 63 { 64 build(1,n,1); 65 while(m--) 66 { 67 scanf("%s",&c); 68 if(c[0]=='Q') 69 { 70 scanf("%d %d",&a,&b); 71 printf("%lld\n",query(a,b,1,n,1)); 72 } 73 else 74 { 75 scanf("%d %d %d",&a,&b,&w); 76 update(a,b,w,1,n,1); 77 } 78 } 79 } 80 return 0; 81 }
posted on 2013-02-07 21:41 acoderworld 阅读(124) 评论(0) 收藏 举报

浙公网安备 33010602011771号