Codeforces915E Physical Education Lessons (线段树 + 区间离散化)

这篇博客介绍了如何使用动态开点线段树解决一个涉及大数(10^9级别)的区间操作问题。在给定的01序列上,可以进行两种操作:将区间内的所有元素置为1或置为0。通过离散化和动态开点线段树,博主展示了如何在操作次数较小(3*10^5)的情况下高效维护区间信息,并给出了AC代码实现。

题目链接: Physical Education Lessons

大致题意

给定一个长度为 n n n 01 01 01序列, 有两种操作: 把区间 [ l , r ] [l, r] [l,r]全部变为 1 1 1, 或把区间 [ l , r ] [l, r] [l,r]全部变为 0 0 0.

每次操作结束后, 输出序列中 1 1 1的个数.

解题思路

➡️题目弱化版推荐⬅️
➡️珂朵莉树做法题解⬅️

线段树

我们考虑到如果 n n n比较小(在 1 0 6 10^6 106以内), 我们可以直接用线段树暴力维护区间信息.

但是本题的 n n n很大(有 1 0 9 10^9 109), 我们没法通过堆存储的方式用静态开点线段树来维护. 但是考虑到操作 m m m比较小, 只有 3 ⋅ 1 0 5 3·10^5 3105, 因此涉及到的点个数至多为 2 m 2m 2m. 我们可以采用动态开点的线段树来维护.

但是我们还有一种更节省空间的方式 — 把用到的所有点进行离散化. 但是这样离散化后, 会使得原本不连续的点变得连续, 我们需要再额外插入一些有权值的点, 使得这些点仍然保持不连续.

例如: 如果现在用到的端点有3和7, 离散化后就变成了1和2, 但本身3和7是不挨着的(中间还有4, 5, 6). 但是离散化后, 1和2是挨着的(4, 5, 6这三个点被错误的丢弃了).


因此我们正确的做法是, 在3和7两个点之间再插入一个带有权值的点4, 权值为3(表示4, 5, 6这三个点).

为了便于叙述, 我们不妨把所有的点都看作一个点对 ( x , y ) (x, y) (x,y), 其中

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值