Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

懒标记

线段树要做到其 \(O(\log n)\) 的更新和查询,就需要用到懒标记。

懒标记的作用是,当我们对线段树的某些节点(区间)进行更新时,我们并不立即更新这些节点的值,而是将这些更新操作延迟到下一次查询或更新时再进行。

洛谷已经为我们排好了对线段树的逐层深度学习XD


P3372 【模板】线段树 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5,maxm=1e5;
typedef long long ll;
void read(int &x)
{
char c=getchar();
while(c<'0' or c>'9')c=getchar();
x=c-'0',c=getchar();
while(c>='0' and c<='9'){
x*=10,x+=c-'0',c=getchar();
}
}
int a[maxn*10];
struct node{
ll l,r,sum,tag;
}e[maxn*6];
int n,m,k;
inline ll ls(ll ro){return ro<<1;}
inline ll rs(ll ro){return ro<<1|1;}
inline void push_up(ll ro)
{
e[ro].sum=e[ls(ro)].sum+e[rs(ro)].sum;
}
inline void push_down(ll ro)
{
e[ls(ro)].sum+=e[ro].tag*(e[ls(ro)].r-e[ls(ro)].l+1);
e[rs(ro)].sum+=e[ro].tag*(e[rs(ro)].r-e[rs(ro)].l+1);
e[ls(ro)].tag+=e[ro].tag;
e[rs(ro)].tag+=e[ro].tag;
e[ro].tag=0;
}

void build(ll ro,ll l,ll r)
{
e[ro].l=l,e[ro].r=r;
if(l==r)
{
e[ro].sum=a[l];
return;
}
e[ro].tag=0;
ll mid=(l+r)>>1;
build(ls(ro),l,mid);
build(rs(ro),mid+1,r);
push_up(ro);
}

void update(ll ro,ll l,ll r)
{
if(e[ro].l>=l and r>=e[ro].r)
{
e[ro].sum+=k*(e[ro].r-e[ro].l+1);
e[ro].tag+=k;
return;
}
push_down(ro);
ll mid=(e[ro].l+e[ro].r)>>1;
if(l<=mid)update(ls(ro),l,r);
if(r> mid)update(rs(ro),l,r);
push_up(ro);
}

ll check(ll ro,ll l,ll r)
{
if(l<=e[ro].l and r>=e[ro].r)return e[ro].sum;
push_down(ro);
int mid=(e[ro].l+e[ro].r)>>1;
ll ans=0;
if(l<=mid)ans+=check(ls(ro),l,r);
if(r> mid)ans+=check(rs(ro),l,r);
return ans;
}
signed main()
{
read(n);read(m);
for(int i=1;i<=n;i++)
read(a[i]);
build(1,1,n);
int casee,l,r;
for(int i=1;i<=m;i++)
{
read(casee);
switch(casee)
{
case(1):{
read(l);read(r);read(k);
update(1,l,r);
break;
}
case(2):{
read(l);read(r);
printf("%lld\n",check(1,l,r));
break;
}
}
}
return 0;
}

P3373 【模板】线段树 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5;
typedef long long ll;
int n,m,p,a[maxn],k;
struct tree{
ll l,r,val,add,tag;
}e[maxn*4];
inline void read(int &x)
{
char c=getchar();
while(c<'0' or c>'9')c=getchar();
x=c-'0',c=getchar();
while(c>='0' and c<='9')x*=10,x+=c-'0',c=getchar();
}
inline ll ls(int ro){return ro<<1;}
inline ll rs(int ro){return ro<<1|1;}

inline void lazy_add(ll ro)
{
e[ls(ro)].add=(e[ls(ro)].add*e[ro].tag+e[ro].add)%p;
e[rs(ro)].add=(e[rs(ro)].add*e[ro].tag+e[ro].add)%p;
}

inline void lazy_tag(ll ro)
{
e[ls(ro)].tag=(e[ls(ro)].tag*e[ro].tag)%p;
e[rs(ro)].tag=(e[rs(ro)].tag*e[ro].tag)%p;
}

inline void push_down(ll ro)
{
e[ls(ro)].val=(e[ls(ro)].val*e[ro].tag+e[ro].add*(e[ls(ro)].r-e[ls(ro)].l+1))%p;
e[rs(ro)].val=(e[rs(ro)].val*e[ro].tag+e[ro].add*(e[rs(ro)].r-e[rs(ro)].l+1))%p;
lazy_tag(ro);
lazy_add(ro);
e[ro].add=0,e[ro].tag=1;
}

inline void push_up(ll ro)
{
e[ro].val=(e[ls(ro)].val+e[rs(ro)].val)%p;
}

void build(ll ro,ll l ,ll r)
{
e[ro].l=l,e[ro].r=r;
e[ro].tag=1,e[ro].add=0;
if(l==r){e[ro].val=a[l];return;
}
int mid=(l+r)>>1;
build(ls(ro),l,mid);
build(rs(ro),mid+1,r);
push_up(ro);
e[ro].val%=p;
}

void update_tag(ll ro,ll l ,ll r)
{
if(e[ro].l>=l and e[ro].r<=r)
{
e[ro].val=(e[ro].val*k)%p;
e[ro].tag=(e[ro].tag*k)%p;
e[ro].add=(e[ro].add*k)%p;
return ;
}
push_down(ro);
int mid=(e[ro].l+e[ro].r)>>1;
if(l<=mid)update_tag(ls(ro),l,r);
if(r> mid)update_tag(rs(ro),l,r);
push_up(ro);
}

void update_add(ll ro,ll l,ll r)
{
if(e[ro].l>=l and e[ro].r<=r)
{
e[ro].add=(e[ro].add+k)%p;
e[ro].val=(e[ro].val+k*(e[ro].r-e[ro].l+1))%p;
return ;
}
push_down(ro);
int mid=(e[ro].l+e[ro].r)>>1;
if(l<=mid)update_add(ls(ro),l,r);
if(r> mid)update_add(rs(ro),l,r);
push_up(ro);
}

ll query(ll ro,ll l,ll r)
{
if(e[ro].l>=l and e[ro].r<=r)
return e[ro].val;
push_down(ro);
int mid=(e[ro].l+e[ro].r)>>1;
int ans=0;
if(l<=mid) ans+=query(ls(ro),l,r);
if(r> mid) ans+=query(rs(ro),l,r);
return ans%p;
}
int main()
{
read(n);read(m);read(p);
for(int i=1;i<=n;i++)read(a[i]);
build(1,1,n);
int casee,l,r;
while(m--)
{
read(casee);
switch(casee)
{
case(1):{
read(l);read(r);read(k);
update_tag(1,l,r);
break;
}
case(2):{
read(l);read(r);read(k);
update_add(1,l,r);
break;
}
case(3):{
read(l);read(r);
printf("%lld\n",query(1,l,r));
break;
}
}
}
return 0;
}

P6242 【模板】线段树 3

我不会XD

给小狼留言