poj 3468 线段树 成段增减 区间求和

题意:Q是询问区间和,C是在区间内每个节点加上一个值

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output

4
55
9
15

  1 # include <iostream>
  2 # include <cstdio>
  3 # include <cstring>
  4 # include <algorithm>
  5 # include <cmath>
  6 # include <queue>
  7 # define LL long long
  8 using namespace std ;
  9
 10
 11 const int maxn = 100010;
 12
 13 LL sum[maxn<<2] ; //结点开4倍
 14 LL add[maxn<<2] ; //延迟标记
 15
 16 void PushUP(int rt) //更新到父节点
 17 {
 18     sum[rt] = sum[rt * 2] + sum[rt * 2 + 1] ; //rt 为当前结点
 19 }
 20
 21 void PushDown(int rt , int m )  //向下更新
 22 {
 23     if (add[rt])
 24     {
 25         add[rt * 2] += add[rt] ;
 26         add[rt * 2 + 1] += add[rt] ;
 27         sum[rt * 2] += (m - m / 2) * add[rt] ;
 28         sum[rt * 2 + 1] += (m / 2) * add[rt] ;
 29         add[rt] = 0 ;
 30     }
 31 }
 32
 33 void build(int l , int r , int rt) //构建线段树
 34 {
 35     add[rt] = 0 ;
 36     if (l == r)
 37     {
 38         cin>>sum[rt];
 39         return ;
 40     }
 41     int m = (l + r) / 2 ;
 42     build(l , m , rt * 2) ;
 43     build(m + 1 , r , rt * 2 +1) ;
 44     PushUP(rt) ;
 45 }
 46
 47 void updata(int L , int R , int c , int l , int r , int rt)  //成段增减
 48 {
 49     if (L <= l && r <= R)
 50         {
 51             add[rt] += c ;
 52             sum[rt] += (r - l + 1) * c ;
 53             return  ;
 54         }
 55     PushDown(rt , r - l + 1) ;
 56     int m = (l + r) / 2 ;
 57
 58     if (L <= m)
 59        updata(L , R , c , l , m , rt * 2) ;
 60     if (R > m)
 61        updata(L , R , c , m + 1 , r , rt * 2 + 1) ;
 62     PushUP(rt) ;
 63 }
 64
 65 LL query(int L , int R , int l , int r , int rt)  //区间求和
 66 {
 67     if (L <= l && r <= R)
 68         return sum[rt] ;
 69     PushDown(rt , r - l + 1) ;
 70     int m = (l + r) / 2 ;
 71     LL ret = 0 ;
 72     if (L <= m)
 73        ret += query(L , R , l , m , rt * 2) ;
 74     if (R > m)
 75        ret += query(L , R , m + 1 , r , rt * 2 + 1) ;
 76     return ret ;
 77 }
 78
 79 int main ()
 80 {
 81     //freopen("in.txt","r",stdin) ;
 82     int n , m ;
 83     scanf("%d %d" , &n , &m) ;
 84
 85         build(1 , n , 1) ;
 86         while(m--)
 87         {
 88             char op[10] ;
 89             int a , b , c ;
 90             scanf("%s" , op) ;
 91             if(op[0] == ‘Q‘)
 92             {
 93                 scanf("%d %d" , &a , &b) ;
 94                 cout<<query(a , b , 1 , n , 1)<<endl ;
 95             }
 96             else
 97             {
 98               scanf("%d %d %d" , &a , &b , &c) ;
 99               updata(a , b , c , 1 , n , 1) ;
100             }
101         }
102
103
104
105     return 0 ;
106 }

时间: 2024-10-13 12:22:30

poj 3468 线段树 成段增减 区间求和的相关文章

poj 3468 线段树成段更新

http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58132   Accepted: 17704 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two k

(线段树成段更新+区间求和) poj 3468

D - A Simple Problem with Integers Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3468 Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One typ

poj 3669 线段树成段更新+区间合并

添加 lsum[ ] , rsum[ ] , msum[ ] 来记录从左到右的区间,从右到左的区间和最大的区间: #include<stdio.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 50005 int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];//msum[]维护区间1…N中的最大连续区间长度 int

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

HDU 3397 Sequence operation(线段树&#183;成段更新&#183;区间合并&#183;混合操作)

题意  给你一个只有0, 1的数组  有这些操作 0. 将[a, b]区间的所有数都改为0 1. 将[a, b]区间的所有数都改为1 2. 将[a, b]区间的所有数都取反 即与1异或 3. 输出区间[a, b]中1的个数  即所有数的和 4. 输出区间[a, b]中最大连续1的长度 对于所有的3, 4操作输出对应的答案 单个的操作都很简单  但搞在一起就有点恶心了  还好数组里的数只有0和1 线段树维护9个值 对应区间0, 1的最大长度len[i]  对应区间左端点为起点的最大0, 1长度ll

C - A Simple Problem with Integers POJ - 3468 线段树模版(区间查询区间修改)

参考qsc大佬的视频 太强惹 先膜一下 视频在b站 直接搜线段树即可 1 #include<cstdio> 2 using namespace std; 3 const int maxn=1e5+6; 4 int n,a[maxn]; 5 struct Node{ 6 int l,r; 7 long long sum,lazy; 8 void update(long long x){//用于更新区间和 和懒标记 9 sum+=1ll*(r-l+1)*x; 10 lazy+=x; 11 } 12

hdu 1166 线段树(单点增减 区间求和)

Sample Input1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End Sample OutputCase 1:63359 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath>

POJ3468 A Simple Problem with Integers(线段树成段增减,区间求和)

题意:一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和.(这里区间指的是数列中连续的若干个数)对每次询问给出结果. #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <cmath> #include <algorithm> usi

poj 2777 Count Color (成段更新+区间求和)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 36646   Accepted: 11053 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.