脑洞治疗仪

P4344 [SHOI2015] 脑洞治疗仪

翻译题目

  • \(0\quad l\quad r\):区间置 \(0\)

  • \(1\quad l_0\quad r_0\quad l_1\quad r_1\):将 \([l_0,r_0]\) 中的 \(1\) 取出,填到 \([l_1,r_1]\)(从左到右填入,多出去的扔掉)。

  • \(2\quad l\quad r\),查询区间内最大连续 \(0\) 的长度。

思路

我们考虑维护类似于最大子段和的信息:(1)左边连续 0、(2)右边连续 0、(3)答案、(4)长度、(5)1 的个数。

为了方便,定义 \(l\) 表示左子树的区间,\(r\) 代表右子树的区间。

更新:

  1. 如果 \(l\)\(1\),那么肯定不可能穿透到 \(r\),就是 \(l\) 的(1);否则,\(l\) 的长度+ \(r\) 的(1)。
  2. 如果 \(r\)\(1\),那么肯定不可能穿透到 \(l\),就是 \(r\) 的(2);否则,\(r\) 的长度+ \(l\) 的(2)。
  3. l答案、r答案、l(2)+r(1)最大者。
  4. 不更新。
  5. 相加。

操作1:懒标记,直接更新。

操作2:二分找到可以填充的最右边的位置,然后操作1+区间置1。

操作3:询问若干个区间,然后像3一样合并答案,需要注意l(2),r(1)不能超出询问的区间边界。

code

我们可以写一个函数模拟填入的过程。

如果区间对应的只有左子树或右子树,直接填就行。

如果两个都有,我们先填左子树,再把剩下的给右子树填。

每次发现一个区间可以直接填时直接填,然后懒标记与操作2中的区间置1一样,打懒标记是 \(O(1)\) 的。

这样复杂度就少了一个log。

code

posted @ 2023-10-06 14:31  wscqwq  阅读(2)  评论(0编辑  收藏  举报