0%

ITMO Academy pilot course » Segment Tree, part 1 » Step 2 » Practice(ITMO 线段树部分1,第2步的练习,单点修改线段树,线段树上二分)

题目1(单点修改、区间查询、最大子段和)

题目大意

给定一个长度为 nn 的数组 aa,初始元素范围为 109ai109-10^9 \le a_i \le 10^9。你需要处理 mm 次操作,每次操作将索引 ii 处的元素修改为 vv

你需要输出 m+1m+1 行结果

  1. 在所有操作之前,数组中最大子段和(连续子数组的最大和)。

  2. 在每次修改操作后,当前数组的最大子段和

注意

  • 子段可以为空,空子段的和定义为 00。因此答案至少为 00

  • 1n,m1000001 \le n, m \le 100000

  • 索引 ii00 开始 (0i<n0 \le i < n)。

输入格式

第一行包含两个整数 nnmm
第二行包含 nn 个整数,表示数组的初始状态。
接下来的 mm 行,每行包含两个整数 iivv,表示将 aia_i 修改为 vv

输出格式

输出共 m+1m+1 行,每行一个整数,表示当前状态下的最大子段和。

样例 1

1
2
3
4
5 2
5 -4 4 3 -5
4 3
3 -1

样例 1 输出

1
2
3
8
11
7

样例 1 解释

  1. 初始状态:数组为 [5, -4, 4, 3, -5]
  • 最大子段和为 5+(4)+4+3=85 + (-4) + 4 + 3 = 8(索引 0033)。
  • 输出 8
  1. 第一次操作 4 3:将 a4a_4 修改为 33
  • 数组变为 [5, -4, 4, 3, 3]
  • 最大子段和为 5+(4)+4+3+3=115 + (-4) + 4 + 3 + 3 = 11(索引 0044)。
  • 输出 11
  1. 第二次操作 3 -1:将 a3a_3 修改为 1-1
  • 数组变为 [5, -4, 4, -1, 3]
  • 最大子段和为 5+(4)+4+(1)+3=75 + (-4) + 4 + (-1) + 3 = 7(索引 0044)。
  • 输出 7

样例 2

1
2
3
4
4 2
-2 -1 -5 -4
1 3
3 2

样例 2 输出

1
2
3
0
3
3

样例 2 解释

  1. 初始状态:数组全为负数 [-2, -1, -5, -4],最大子段为空子段,和为 0

  2. 第一次操作 1 3:数组变为 [-2, 3, -5, -4],最大子段为 [3],和为 3

  3. 第二次操作 3 2:数组变为 [-2, 3, -5, 2],最大子段仍为 [3],和为 3

我们的这个程序就是直接,Max 0LL去解决这个最小值不能小于0的这个问题。

AC
https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/submission/363498742

P4513 小白逛公园

https://www.luogu.com.cn/problem/P4513

就是这个线段数结构体初值的设定啊,就是 sum 类的一定要负0,不要负什么 inf infinite 这样的值。那么其实付出值并不能够比较好的保证这样子的一个结果。最好的保证结果的方法呢,还是就是不要使用初值去 merge 任何东西。最好就不要使用初值。初值是设定初值只是为了防止报错而已,最好就不要使用初值。

1
2
3
4
5
struct Info {
// 注意啊,这里除了 L 和 R 以外的所有你所添加的东西,你都要好好想一想其初值是什么。
// 不过我们其实改进了这个 query 函数,所以说如果说你给的这个数组当中所有的值都是所有的值都是有的话,其实不用考虑初值。
// 如果一定要赋初值的话,注意就是 sum 类的都不要赋 infinite 然后只有 max 和 min 的你要好好想想。
ll l = 0, r = 0, pre_sum = 0, suf_sum = 0, mx_sum = 0, sum = 0;

AC
https://www.luogu.com.cn/record/263243648

题目2(找到第 K 个一)

这道题目一开始有点问题啊,是因为什么呢?是因为这个0 base 的和1 base 的这个转换转错了。

AC
https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/submission/363516918

题目3 C. First element at least X

题目挖了一发,是因为这个,即便在叶子节点啊,我们也要检查一下,然后再返回。虽然一般来说,我们进入叶子节点的时候,肯定是检查过的。但如果根节点本身就是叶子节点的话,我们可能未执行检查,所以导致错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ll findFirst(ll u,ll l,ll r,F && fun) {
if (infos[u].l==infos[u].r) {
if (fun(infos[u])) return infos[u].l;
return -1;
}
ll res=-1;
if (isIntersect(infos[u<<1].l, infos[u<<1].r, l, r) && fun(infos[u<<1])) {
res=findFirst(u<<1,l,r,fun);
}
if (res!=-1) return res;
if (isIntersect(infos[u<<1|1].l, infos[u<<1|1].r, l, r) && fun(infos[u<<1|1])) {
res=findFirst(u<<1|1,l,r,fun);
}
return res;
}

AC
https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/submission/363525477

题目4 D. First element at least X - 2

那么其实啊,上一题目的代码里面,我已经采用了可以通过这道题目的实现。

AC
https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/submission/363527109