kb-07线段树-03--区间修改查询--lazy思想

  1 /*
  2    区间修改,区间查询和;
  3    第一次使用lazy思想;
  4    poj3468
  5  */
  6 #include<iostream>
  7 #include<cstdio>
  8 #include<cstring>
  9 #include<algorithm>
 10 #define ll long long
 11 using namespace std;
 12 typedef struct
 13 {
 14     int l,r;
 15     ll add;
 16     ll value;
 17 }V;
 18
 19 int n,m,a[100005]={0};
 20
 21 V tr[400010]={0};
 22 void Pushup(int rt)
 23 {
 24     tr[rt].value=tr[rt<<1].value+tr[(rt<<1)|1].value;
 25 }
 26 void Pushdown(int rt,int m)
 27 {
 28     if(tr[rt].add)
 29     {
 30         tr[rt<<1].add+=tr[rt].add;
 31         tr[(rt<<1)|1].add+=tr[rt].add;
 32         tr[rt<<1].value+=tr[rt].add*(m-(m>>1));
 33         tr[(rt<<1)|1].value+=tr[rt].add*(m>>1);
 34         tr[rt].add=0;
 35     }
 36 }
 37 void build(int i,int l,int r)
 38 {
 39     tr[i].l=l;
 40     tr[i].r=r;
 41     tr[i].add=0;
 42     if(l==r)
 43     {
 44         tr[i].value=a[l];
 45         return ;
 46     }
 47     int mid=(l+r)/2;
 48     build(i<<1,l,mid);
 49     build((i<<1)|1,mid+1,r);
 50     Pushup(i);
 51 }
 52 void Update(int i,int l,int r,int x)
 53 {
 54      if(tr[i].l==l&&tr[i].r==r)
 55      {
 56          tr[i].add+=x;
 57          tr[i].value+=(ll)x*(r-l+1);
 58          return ;
 59      }
 60      if(tr[i].l==tr[i].r)
 61          return ;
 62      Pushdown(i,tr[i].r-tr[i].l+1);
 63      int t=i<<1;
 64      if(l<=tr[t].r)
 65      {
 66          if(r<=tr[t].r)
 67              Update(t,l,r,x);
 68          else
 69              Update(t,l,tr[t].r,x);
 70      }
 71      t+=1;
 72      if(r>=tr[t].l)
 73      {
 74          if(l>=tr[t].l)
 75              Update(t,l,r,x);
 76          else
 77              Update(t,tr[t].l,r,x);
 78      }
 79      Pushup(i);
 80 }
 81 ll  Query(int i,int l,int r)
 82 {
 83     if(tr[i].l==l&&tr[i].r==r)
 84     {
 85         return tr[i].value;
 86     }
 87     Pushdown(i,tr[i].r-tr[i].l+1);
 88     ll ans=0;
 89     i=i<<1;
 90     if(l<=tr[i].r)
 91     {
 92         if(r<=tr[i].r)
 93             ans+=Query(i,l,r);
 94         else
 95             ans+=Query(i,l,tr[i].r);
 96     }
 97     i+=1;
 98     if(r>=tr[i].l)
 99     {
100         if(l>=tr[i].l)
101             ans+=Query(i,l,r);
102         else
103             ans+=Query(i,tr[i].l,r);
104     }
105     return ans;
106 }
107 int main()
108 {
109    while(scanf("%d%d",&n,&m)!=EOF)
110    {
111         memset(a,0,sizeof(a));
112         memset(tr,0,sizeof(tr));
113         for(int i=1;i<=n;i++)
114             scanf("%d",&a[i]);
115         build(1,1,n);
116         for(int i=0;i<m;i++)
117         {
118             char s[2];
119             int x1,x2,x3;
120             scanf("%s",s);
121             if(s[0]==‘C‘)
122             {
123                 scanf("%d%d%d",&x1,&x2,&x3);
124                 Update(1,x1,x2,x3);
125             }
126             else
127             {
128                 scanf("%d%d",&x1,&x2);
129                 printf("%I64d\n",Query(1,x1,x2));
130             }
131         }
132    }
133     return 0;
134 }
时间: 2024-08-02 18:58:00

kb-07线段树-03--区间修改查询--lazy思想的相关文章

hihoCode 1078 : 线段树的区间修改

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

hiho一下20周 线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 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 2828 Buy Tickets (线段树,区间修改)

逆向思维.从最后一位开始考虑,用线段树查询空位置. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include &l

模板 线段树的区间修改

线段树的区间修改 区间绝对标记 改成同一个数 注意打标记前 要先判断 是否有标记 这道题不能像加法标记一样 标记初始化为 0 如果这道题 可以将数变成 0 那么0 就不能为初始值了 然后我们初始值要选择一个不会被干扰到的数字 比如 -1 就不会变成 -1 另外还要注意在标记清空时 要将标记 变成 -1 而不是 0 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstr

hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)

题意: 给出一个数组a,叫你每次询问如下等式的值. f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) 解析: 思考了很久终于理解了学长的思路 给你一个序列,这个序列的子序列gcd的个数不会超过logN个(N为每个数字,最大能取到的范围) 因为求gcd是递减的,每次至少除以2,所以gcd的个数只会有logN个. 然后让我们来看看题目要求的是什么. 所有子区间的gcd的和. 比如[1, 5]这个区间可以分解成如下子区间. [1, 1] [1, 2] [1, 3] [1, 4]

培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)

补坑咯~ 今天围绕的是一个神奇的数据结构:线段树.(感觉叫做区间树也挺科学的.) 线段树,顾名思义就是用来查找一段区间内的最大值,最小值,区间和等等元素. 那么这个线段树有什么优势呢? 比如我们要多次查询1-n中的最大值,那么我们如果使用暴力来查找,那么我们每次查找的复杂度就是O(n) 但是如果我们把一个个区间变成树上的一个个点,并且我们严格保证树的深度,那么我们每次查找的复杂度就是O(logn) 这样就能让查询变得更快. 我们先简单讲一下线段树的存储(图中的标号就是线段树数组标号) 这就是线段