【成端更新线段树模板】POJ3468-A Simple Problem with Integers

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 }

 

转载于:https://www.cnblogs.com/iiyiyi/p/5001895.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值