线段树区间更新 lazy

Posted cmyg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树区间更新 lazy相关的知识,希望对你有一定的参考价值。

 

1.

hdu1698

http://acm.hdu.edu.cn/showproblem.php?pid=1698

  1 /*
  2 x y k
  3 x~y的值变为k
  4 */
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <time.h>
 10 #include <string>
 11 #include <set>
 12 #include <map>
 13 #include <list>
 14 #include <stack>
 15 #include <queue>
 16 #include <vector>
 17 #include <bitset>
 18 #include <ext/rope>
 19 #include <algorithm>
 20 #include <iostream>
 21 using namespace std;
 22 #define ll long long
 23 #define minv 1e-6
 24 #define inf 1e9
 25 #define pi 3.1415926536
 26 #define E  2.7182818284
 27 const ll mod=1e9+7;//998244353
 28 const int maxn=1e5+10;
 29 
 30 int tag[maxn<<2],sum[maxn<<2];
 31 
 32 void push_down(int index,int len)
 33 {
 34     tag[index<<1]=tag[index<<1|1]=tag[index];
 35     sum[index<<1]=((len+1)>>1)*tag[index];
 36     sum[index<<1|1]=(len>>1)*tag[index];
 37     tag[index]=0;
 38 }
 39 
 40 void build(int index,int l,int r)
 41 {
 42     tag[index]=0;
 43     if (l==r)
 44         sum[index]=1;
 45     else
 46     {
 47         int m=(l+r)>>1;
 48         build(index<<1,l,m);
 49         build(index<<1|1,m+1,r);
 50         sum[index]=sum[index<<1]+sum[index<<1|1];
 51     }
 52 }
 53 
 54 void update(int index,int l,int r,int x,int y,int k)
 55 {
 56     if (x<=l && r<=y)
 57     {
 58         tag[index]=k;
 59         sum[index]=(r-l+1)*k;
 60         return;
 61     }
 62     if (tag[index]!=0)
 63         push_down(index,r-l+1);
 64     int m=(l+r)>>1;
 65     if (x<=m)
 66         update(index<<1,l,m,x,y,k);
 67     if (m<y)
 68         update(index<<1|1,m+1,r,x,y,k);
 69     sum[index]=sum[index<<1]+sum[index<<1|1];
 70 }
 71 
 72 int query(int index,int l,int r,int s,int t)
 73 {
 74     if (s<=l && r<=t)
 75         return sum[index];
 76     if (r<s || l>t)
 77         return 0;
 78     if (tag[index]!=0)
 79         push_down(index,r-l+1);
 80     int m=(l+r)>>1;
 81     return query(index<<1,l,m,s,t)+query(index<<1|1,m+1,r,s,t);
 82 }
 83 
 84 int main()
 85 {
 86     int t,T,n,q,x,y,k;
 87     scanf("%d",&t);
 88     for (T=1;T<=t;T++)
 89     {
 90         scanf("%d",&n);
 91         build(1,1,n);
 92         scanf("%d",&q);
 93         while (q--)
 94         {
 95             scanf("%d%d%d",&x,&y,&k);
 96             update(1,1,n,x,y,k);
 97         }
 98         printf("Case %d: The total value of the hook is %d.
",T,query(1,1,n,1,n));
 99     }
100     return 0;
101 }

 

2.

https://www.luogu.org/problemnew/show/P3372

  1 /*
  2 第八个测试数据有问题(已看)
  3 
  4 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
  5 
  6 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
  7 */
  8 #include <cstdio>
  9 #include <cstdlib>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <time.h>
 13 #include <string>
 14 #include <set>
 15 #include <map>
 16 #include <list>
 17 #include <stack>
 18 #include <queue>
 19 #include <vector>
 20 #include <bitset>
 21 #include <ext/rope>
 22 #include <algorithm>
 23 #include <iostream>
 24 using namespace std;
 25 #define ll long long
 26 #define minv 1e-6
 27 #define inf 1e9
 28 #define pi 3.1415926536
 29 #define E  2.7182818284
 30 const ll mod=1e9+7;//998244353
 31 const int maxn=1e5+10;
 32 
 33 ll sum[maxn<<2],tag[maxn<<2];
 34 
 35 void build(int index,int l,int r)
 36 {
 37     tag[index]=0;
 38     if (l==r)
 39     {
 40         scanf("%lld",&sum[index]);
 41         sum[index]=sum[index]%mod;
 42     }
 43     else
 44     {
 45         int m=(l+r)>>1;
 46         build(index<<1,l,m);
 47         build(index<<1|1,m+1,r);
 48         sum[index]=(sum[index<<1]+sum[index<<1|1])%mod;
 49     }
 50 }
 51 
 52 void pushdown(int index,ll len)
 53 {
 54     sum[index<<1]=(tag[index]*((len+1)>>1) +sum[index<<1])%mod;
 55     sum[index<<1|1]=(tag[index]*(len>>1) +sum[index<<1|1])%mod;
 56     tag[index<<1]=(tag[index]+ tag[index<<1])%mod;
 57     tag[index<<1|1]=(tag[index]+ tag[index<<1|1])%mod;
 58     tag[index]=0;
 59 }
 60 
 61 void update(int index,int l,int r,int x,int y,ll k)
 62 {
 63     if (x<=l && r<=y)
 64     {
 65         sum[index]=(k*(r-l+1) +sum[index])%mod;
 66         tag[index]=(k +tag[index])%mod;
 67         return;
 68     }
 69     int m=(l+r)>>1;
 70     if (tag[index]!=0)
 71         pushdown(index,r-l+1);
 72     if (x<=m)
 73         update(index<<1,l,m,x,y,k);
 74     if (m<y)
 75         update(index<<1|1,m+1,r,x,y,k);
 76     sum[index]=(sum[index<<1]+sum[index<<1|1])%mod;
 77 }
 78 
 79 ll query(int index,int l,int r,int x,int y)
 80 {
 81     if (x<=l && r<=y)
 82         return sum[index];
 83     if (r<x || l>y)
 84         return 0;
 85     if (tag[index]!=0)
 86         pushdown(index,r-l+1);
 87     int m=(l+r)>>1;
 88     return (query(index<<1,l,m,x,y)+query(index<<1|1,m+1,r,x,y))%mod;
 89 }
 90 
 91 int main()
 92 {
 93     int n,m,mode,x,y;
 94     ll k;
 95     scanf("%d%d",&n,&m);
 96     build(1,1,n);
 97     while (m--)
 98     {
 99         scanf("%d",&mode);
100         if (mode==1)
101         {
102             scanf("%d%d%lld",&x,&y,&k);
103             update(1,1,n,x,y,k%mod);
104         }
105         else
106         {
107             scanf("%d%d",&x,&y);
108             printf("%lld
",query(1,1,n,x,y));
109         }
110     }
111     return 0;
112 }
113 /*
114 10
115 463 793 740 374 330 772 681
116 5 8 39
117 5 8
118 3 6 3
119 5 8 90
120 1 5 21
121 3 8
122 3 8 17
123 4 7 52
124 2 6
125 2 7 41
126 5
127 2 3 4 5
128 1 3 -1
129 1 3 1
130 2 4
131 100
132 2 3 4 5 6 7 8 9 10
133 1 10
134 2 7 1
135 1 10
136 3 8
137 
138 */

 

 

3.

https://www.luogu.org/problemnew/show/P3373

  1 /*
  2 1.将某区间每一个数乘上x
  3 
  4 2.将某区间每一个数加上x
  5 
  6 3.求出某区间每一个数的和
  7 */
  8 #include <cstdio>
  9 #include <cstdlib>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <time.h>
 13 #include <string>
 14 #include <set>
 15 #include <map>
 16 #include <list>
 17 #include <stack>
 18 #include <queue>
 19 #include <vector>
 20 #include <bitset>
 21 #include <ext/rope>
 22 #include <algorithm>
 23 #include <iostream>
 24 using namespace std;
 25 #define ll long long
 26 #define minv 1e-6
 27 #define inf 1e9
 28 #define pi 3.1415926536
 29 #define E  2.7182818284
 30 //const ll mod=1e9+7;//998244353
 31 const int maxn=1e5+10;
 32 
 33 ll mod;
 34 ll add[maxn<<2],mul[maxn<<2],sum[maxn<<2];
 35 int mode;
 36 
 37 void build(int index,int l,int r)
 38 {
 39     add[index]=0;
 40     mul[index]=1;
 41     if (l==r)
 42     {
 43         scanf("%lld",&sum[index]);
 44         sum[index]=sum[index]%mod;
 45     }
 46     else
 47     {
 48         int m=(l+r)>>1;
 49         build(index<<1,l,m);
 50         build(index<<1|1,m+1,r);
 51         sum[index]=(sum[index<<1]+sum[index<<1|1])%mod;
 52     }
 53 }
 54 
 55 void pushdown(int index,ll len)
 56 {
 57     //(x *y+z)*s+t = x*(ys) + z*s+t
 58     add[index<<1]=(add[index<<1]*mul[index]+add[index])%mod;
 59     mul[index<<1]=mul[index]*mul[index<<1]%mod;
 60     sum[index<<1]=(sum[index<<1]*mul[index]+add[index]*((len+1)>>1))%mod;
 61 
 62     add[index<<1|1]=(add[index<<1|1]*mul[index]+add[index])%mod;
 63     mul[index<<1|1]=mul[index]*mul[index<<1|1]%mod;
 64     sum[index<<1|1]=(sum[index<<1|1]*mul[index]+add[index]*(len>>1))%mod;
 65 
 66     add[index]=0;
 67     mul[index]=1;
 68 }
 69 
 70 void update(int index,int l,int r,int x,int y,ll k)
 71 {
 72     if (x<=l && r<=y)
 73     {
 74         if (mode==1)
 75         {
 76             //(x*y+z)*k
 77             sum[index]=sum[index]*k%mod;
 78             add[index]=add[index]*k%mod;
 79             mul[index]=mul[index]*k%mod;
 80         }
 81         else
 82         {
 83             //(x*y+z)+k
 84             sum[index]=(sum[index]+k*(r-l+1))%mod;
 85             add[index]=(add[index]+k)%mod;
 86         }
 87         return;
 88     }
 89     pushdown(index,r-l+1);
 90     int m=(l+r)>>1;
 91     if (x<=m)
 92         update(index<<1,l,m,x,y,k);
 93     if (m<y)
 94         update(index<<1|1,m+1,r,x,y,k);
 95     sum[index]=(sum[index<<1]+sum[index<<1|1])%mod;
 96 }
 97 
 98 ll query(int index,int l,int r,int x,int y)
 99 {
100     if (x<=l && r<=y)
101         return sum[index];
102     if (x>r || y<l)
103         return 0;
104     pushdown(index,r-l+1);
105     int m=(l+r)>>1;
106     return (query(index<<1,l,m,x,y)+query(index<<1|1,m+1,r,x,y))%mod;
107 }
108 
109 int main()
110 {
111     int n,q,x,y;
112     ll k;
113     scanf("%d%d%lld",&n,&q,&mod);
114     build(1,1,n);
115     while (q--)
116     {
117         scanf("%d%d%d",&mode,&x,&y);
118         if (mode!=3)
119         {
120             scanf("%lld",&k);
121             update(1,1,n,x,y,k%mod);
122         }
123         else
124             printf("%lld
",query(1,1,n,x,y));
125     }
126     return 0;
127 }
128 /*
129 5 100 1000000
130 1 2 3 4 5
131 1 1 5 2
132 2 1 5 3
133 3 1 3
134 
135 */

 

以上是关于线段树区间更新 lazy的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1698 Just a Hook 线段树区间更新

线段树区间更新 lazy

线段树区间更新

模板线段树区间修改

POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

线段树&树状数组