线段树
最大数
给定一个正整数数列a1,a2,…,an
,每一个数都在0∼p−1
之间。
可以对这列数进行两种操作:
- 添加操作:向序列后添加一个数,序列长度变成
n+1
; - 询问操作:询问这个序列中最后 L 个数中最大的数是多少。
如果该行的内容是 Q L
,则表示这个操作是询问序列中最后 L
个数的最大数是多少;
如果是 A t
,则表示向序列后面加一个数,加入的数是
(t+a) mod p
。其中,t是输入的参数,a
是在这个添加操作之前最后一个询问操作的答案(如果之前没有询问操作,则
a=0)。
基本模版
1 |
|
你能回答这些问题吗
给定长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:
1 x y
,查询区间 [x,y] 中的最大连续子段和,即\(\max\limits_{x\leq l\leq r \leq y}\left\{\sum\limits_{i=l}^r A[i]\right\}\)。2 x y
,把 A[x] 改成 y。
对于每个查询指令,输出一个整数表示答案。
线段树结构体中要记录的有
l,r,max
max向上传递有三种情况
- 问的区间恰好在区间的左半边
- 问的区间恰好在区间的右半边
- 问的区间横跨两个区间
那么这个时候就需要记录左半边的右端点最大连续字段和以及右半边的左端点的最大连续字段和,以及整个区间的最大连续字段和
1 |
|
区间最大公约数
给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:
C l r d
,表示把A[l],A[l+1],…,A[r]A[l],A[l+1],…,A[r]
都加上d
。Q l r
,表示询问A[l],A[l+1],…,A[r]A[l],A[l+1],…,A[r]
的最大公约数(GCD)。
对于每个询问,输出一个整数表示答案。
- 涉及把一个区间都加上一个数,且求的是公约数,可以想到用差分;线段数结构体存储
l,r,sum,d
,sum用来计算差分数组的前缀和即原数组,d用来记录差分- 查询操作:因为
gcd(a, b, c) = gcd(a, b - a, c - a)
,所以求[l,r]
区间的最大公约数可以求l.sum
即a[i]
和r.d
即[l + 1, r]
差分的最大约数(在l + 1 <= r
的情况下)- 更改操作:因为是差分,所以在第l个位置加上d,如果
r + 1 <= n
就减去d
1 |
|
一个简单的整数问题2
给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:
C l r d
,表示把 \(A[l],A[l+1],…,A[r]\) 都加上 d。Q l r
,表示询问数列中第 l∼r 个数的和。
对于每个询问,输出一个整数表示答案。
利用懒标记pushdown()
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 眨眼的小星星!