【成端更新线段树模板】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 }
时间: 2024-08-06 03:22:10

【成端更新线段树模板】POJ3468-A Simple Problem with Integers的相关文章

线段树专题 POJ3468 A Simple Problem with Integers

题意:n个点.m个操作.两种操作类型.C X Y K 表示区间[x,y]上每一个点值加k.Q X Y 求区间[x,y]的和 分析:线段树区间求和,裸模板 注意:结果会超int,要用long long 表示,假设是在hust上交结果要用%I64d.poj的话则用%lld 代码: #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algor

(线段树模板)A Simple Problem with Integers --POJ--3468

链接: http://poj.org/problem?id=3468 代码: 1 #include<stdio.h> 2 #include<algorithm> 3 #include<stdlib.h> 4 using namespace std; 5 6 #define Lson r<<1 7 #define Rson r<<1|1 8 9 const int N = 1e5+5; 10 11 struct SegmentTree 12 { 1

POJ 3468 (线段树 区间增减) A Simple Problem with Integers

这题WA了好久,一直以为是lld和I64d的问题,后来发现是自己的pushdown函数写错了,说到底还是因为自己对线段树理解得不好. 因为是懒惰标记,所以只有在区间分开的时候才会将标记往下传递.更新和查询都要pushdown. 1 #include <cstdio> 2 3 typedef long long LL; 4 5 const int maxn = 100000 + 10; 6 7 int n, m, qL, qR, v; 8 LL sum[maxn << 2], add

线段树 POJ 3468 A Simple Problem with Integers

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

POJ3468 A Simple Problem with Integers 【线段树】+【成段更新】

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 57666   Accepted: 17546 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj------(3468)A Simple Problem with Integers(区间更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 60745   Accepted: 18522 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj3468 A Simple Problem with Integers

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

点更新线段树模板

点更新线段树 对一列数,对每次询问输出对应区间的和,每次修改只修改一个数的值... 定义: struct tree { int l,r;//记录代表的区间 int sum;//代表区间的和 } 由于线段树还是相对比较平衡的,所以可以使用数组t来存储这棵树,对与某个节点i,t[i*2]就是左子树,t[i*2+1]就是右子树建树:线段树的思想是每个节点记录区间的信息,某点区间1~n,则1~n/2为其左子树,n/2+1~n为其右子树,每次建立子树方法相同,可以递归建树...至于询问,如果询问区间并不是

POJ-3468 A Simple Problem with Integers(线段树、段变化+段查询、模板)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 116441   Accepted: 36178 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o