【BZOJ十连测】线段树

问题描述

小D写完了随机哈夫曼树,凭信仰开始补觉,想起了在ZJOI见过的一个模型:

  • 给出一个长度为𝑛的数组𝑎,1 ∼ 𝑛标号。
  • 𝑚个操作,每个操作有两个参数𝑙𝑖, 𝑟𝑖,表示将区间[𝑙𝑖, 𝑟𝑖]中的所有数修改为这个区间值。

这个问题可以简单地用线段树来完成,现在小𝐷将这个问题扩展了一下。
给出一个长度为𝑛的初始数组𝑎,以及𝑚个操作,需要维护:

  • 求依次进行编号为[𝐿,𝑅]的这一段操作后𝑎𝑘的值。这些询问互相独立,即可以理解为“假如进行这一段操作后,𝑎𝑘的值会变成多少”。
  • 将𝑎𝑢的值修改为𝑣,即修改初始数组,这次修改会影响它之后的所有询问。

可以参考输入格式来帮助理解题意。

输入格式

从文件segment.in中读入数据。
第一行,三个正整数𝑛, 𝑚, 𝑞,表示数组长度,操作数和询问数。
第二行,𝑛个正整数𝑎𝑖。

输出格式

输出到文件segment.out中。
对于每次询问输出一行一个正整数,表示“假如进行编号为[𝐿,𝑅]的这一段操作后𝑎𝑘的值”。

数据规模

对于10%的数据,𝑛, 𝑚, 𝑞 ≤ 100。
对于30%的数据,𝑛, 𝑚, 𝑞 ≤ 10000。
对于另20%的数据,询问时𝐿 = 1。
对于80%的数据,𝑛, 𝑚, 𝑞 ≤ 50000(包含前一档𝐿 = 1)。
对于100%的数据,𝑛, 𝑚, 𝑞 ≤ 105,1 ≤ 𝑎𝑖, 𝑣 ≤ 105。

Solution

首先我们知道一个性质:区间max是会传递的(前一次传递给后一次)。

那么是不是就意味着,如果我们知道了l到r时间之间与查询区间相交的区间,并不断延伸出去(往上一辈),最后在形成的大区间内查找max就行了?

仔细思考,(好吧其实我思考不出来 )我们可以用倍增的思想来解决这个问题。

先看看倍增递推式:

f [ i ] [ j ] = f [ f [ i ] [ j − 1 ] ] [ j − 1 ] f[i][j]=f[f[i][j-1]][j-1] f[i][j]=f[f[i][j1]][j1]

如果我们将 f [ i ] [ 0 ] f[i][0] f[i][0]赋值为 包 含 x [ i ] 且 在 i 操 作 之 前 的 操 作 j , 这 个 j 离 i 最 近 包含x[i]且在i操作之前的操作j,这个j离i最近 x[i]ijji。那是不是就可以一层层推上去了?

听到这里,你可能会疑惑:为什么不让j与i尽量远?这样不是更省时吗?显然这会错。因为我们最后要找的是保证大于等于l的延展最远的区间,如果取最远的j就可能取不到一些关键点。

Code

不是我不想写,是因为实在找不到原题。。。

我只是代码的传递者:lbww

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值